摘 要:本文以上海市油品公司管理信息系统为例,介绍了使用公共电子邮件信箱,汇集远程数据的技术实现方案。涉及在PowerBuilder开发环境中集成Windows远程拨号管理和邮件自动收发技术。
关键词:分布式数据 EMAIL 远程拨号
一、背景
数据分布处理是目前IT行业的热门话题,出现了许多应用方案。对于一个小型信息系统来说,由于受到技术和成本的限制,如何处理分布式远程数据仍然是一个让系统分析员和设计人员深感头疼的事情。在开发上海市油品公司物流系统的过程中,笔者就遇到这种问题。在介绍实际处理方法之前,让我们首先看一下该系统的背景。
油品公司是上海燃料总公司下属的独立核算企业,拥有近30个联营公司,分布在全国各地。为了强化企业管理,增强竞争能力,公司领导决定根据主要业务,开发一套油品进销存管理信息系统及决策支持系统,该系统不仅用于企业自动化管理,更主要是提供决策数据。经过业务调查和分析,整个系统采用C/S体系结构设计,前端使用Powerbuilder开发,后端DBMS为SQL Server,在企业局域网内运行。相继完成了物流模块、财务数据接口程序以及辅助经理决策系统的开发。在系统试运行的过程中,企业领导提出将各联营公司的经营情况也纳入本系统,要求不受时空的限制,随时随地能从网络中查看各联营公司的计划、分销和资金运作的指标及趋势分析,这就要求系统不仅能处理公司内部业务,而且还能够处理分布在30来个联营企业的报表数据。实际上,这些联营单位可以分为三类,即经营公司、加油站和配送公司,每类公司的数据和功能基本相同。新模块要求将各公司的统计数据分别按日、周、月规定上报,通过总公司中心数据库将这些子集数据再次汇总,不涉及具体业务管理。因此,我们称之为数据申报模块。为了将这些类型固定、数据量小但分布广泛的信息集中汇总,我们考虑了如下几种数据传递方案。
二、选择方案
方案一:使用电话拨号到总公司局域网
这是一种将传统C/S结构程序延续到企业外部的方法,对开发人员来说不需要学习新的编程技巧,只需要通过数据管道,将本地数据库数据转入到远程服务器即可。其缺点在于,由于联营公司数目众多,数据量小但传递频繁,这就需要总公司配备拨号服务器和Modem池,大大提高了系统开发成本;同时各联营公司属于独立核算的外部企业,拨号方式对总公司局域网有很大的安全威胁;而且上海市外的多家联营公司通过长途电话传递数据,通信费用昂贵,不是一个长久之计。
方案二:开发电子商务网站
基于总公司现有数据库系统,制作动态网页,符合油品公司将来extranet或电子商务的发展方向。但是开发网站完全是一个新项目,目前仅仅为了实现数据传递而实施它,不符合客观条件。程序员也需要掌握动态网页制作,学习新技术必将影响到项目进度,这也是约束条件之一。
方案三:通过Internet的公共email信箱实现数据传递
这是方案一的一种变通方法,基本思路是:联营公司将记录输入本地数据库,数据申报时将数据库文件加密、压缩,作为附件发送到事先指定的公共信箱,同时把这些记录拷贝到历史数据库,用于查询和维护。总公司系统管理员定时从信箱中接收文件并解压、解密,使用数据管道将数据转入中心数据库。这种方法有效地克服了方案一的缺点,避免了外部企业拨号进入局域网造成的安全威胁以及对拨号服务器的硬件要求,降低了开发成本,自有的加密、加压算法也保证了数据在公共信箱上的安全性。
从安全性、开发成本、进度等多个角度考虑,我们决定采用方案三实现数据申报模块。实际开发过程中,为了减少系统管理员的工作量和增加系统集成度,隐藏数据异步复制的细节,我们使用有关的API接口函数,集成Windows拨号程序,实现email的自动发送和接收。
三、拨号程序
(下述程序由PowerBuilder6.0编译并调试通过。)
(1)定义拨号API外部函数
function ulong RasCreatePhonebookEntryA( uint hwnd, ref string lpszPhonebook ) library 'Rasapi32.dll' //新建拨号连接
function ulong RasEditPhonebookEntryA( uint hwnd, ref string lpszPhonebook,ref string lpszEntryName ) library 'Rasapi32.dll'
//编辑拨号连接
function ulong RasDeleteEntryA( ref string lpszPhonebook,ref string lpszEntryName ) library 'Rasapi32.dll' //删除拨号连接
注:hwnd为新建拨号连接窗口的父窗口的句柄;
lpszPhonebook为电话本名称,在Win9X下无效,可设为空字符串;
lpszEntryName为拨号连接登记项的名称。
(2)检索已有的拨号连接登记项
public function integer wf_getentries ();
string ls_valuearray[]
int i
RegistryValues("HKEY_USERS\.Default\RemoteAccess\Addresses",ls_valuearray)
for i=1 to UpperBound (ls_valuearray)
lb_1.AddItem(ls_valuearray[i]) // lb_1是ListBox对象,显示已建立的连接名称
next
return UpperBound (ls_valuearray)
end function
(3)拨号及维护(新建、编辑、删除)拨号连接登记项
string ls_Phonebook, ls_DialName
Integer ll_SelectedIndex
ls_Phonebook = “”
ls_DialName = lb_1.SelectedItem()
//在当前窗口中新建拨号连接
dwResult = RasCreatePhonebookEntryA(handle(parent), ls_Phonebook)
//在当前窗口中指定修改拨号连接的属性
dwResult = RasEditPhonebookEntryA( handle(parent),ls_Phonebook, ls_DialName)
//删除指定的拨号连接
dwResult = RasDeleteEntryA(ls_Phonebook, ls_DialName)
//拨号
Run("rundll32.exe rnaui.dll,RnaDial " + ls_DialName)
四、EMAIL收发程序
MAPI是微软定义的一个标准消息应用程序接口,被包含在Windows API中。但我们不需要直接调用API,PowerBuilder已经提供了MAPI的接口,可以利用mailsession事务对象来完成邮件收发。
1. 发送邮件
mailSession mSes //邮件事务对象
mailReturnCode mRet //返回码
mailMessage mMsg //消息对象
// 创建邮件事务对象
mSes = create mailSession
// 登录到邮件服务器
mRet = mSes.mailLogon(mailDownLoad!)
if mRet <> mailReturnSuccess! then
MessageBox("Mail", 'Logon failed.')
return
end if
// 写入消息标题头和附件
mMsg.Subject = 'transport data' //数据邮件标志字符串
mMsg.Recipient[1].name = 'databox@demo.com.cn' //总公司公共信箱
mMsg.AttachmentFile[1].Pathname = 'DatabaseFileName.zip' //压缩后的数据库文件
// 发送邮件
mRet = mSes.mailSend(mMsg)
if mRet <> mailReturnSuccess! then
MessageBox("Mail Send", 'Mail not sent')
return
end if
//退出登录
mSes.mailLogoff()
destroy mSes
2.接收邮件
mailSession mSes
mailReturnCode mRet
mailMessage mMsg
long n
// 创建邮件事务对象
mSes = create mailSession
// 登录到邮件服务器,下载新邮件
mRet = mSes.mailLogon(mailDownLoad!)
//得到邮件消息标志ID
mSes.mailGetMessages(true)
for n = 1 to UpperBound(mSes.MessageID[])
//阅读邮件,将附件存入中间文件夹
mSes.mailReadMessage(mSes.MessageID[n], mMsg, mailEntireMessage!, true)
if mMsg.Subject = 'transport data' then
if UpperBound(mMsg.AttachmentFile[]) > 0 then
// 批处理程序TRANS.BAT为:move %1 %2
Run("TRANS.BAT "+ mMsg.AttachmentFile[1].Pathname + " "+&
tempdirector, Minimized!)
end if
mRet = mSes.mailDeleteMessage(mSes.MessageID[n]) //删除该邮件
end if
next
//退出登录
mSes.mailLogoff()
destroy mSes
五、小结
使用email实现远程数据异步处理,对没有实时和同步要求的应用是一种有效的方法,在进度约束和方案经济可行的条件下,它成功地达到了及时汇总远程数据的目的,受到公司领导和用户的好评。
参考文献
1.Herbert.S.PowerBuilder5.0程序设计大全.北京:机械工业出版社,1997
2.D.Solomon,R.RanKins等.SQL Server6.5开发指南.北京:清华大学出版社,1998
3.刘红岩等著.PowerBuilder原理与应用指南.北京:电子工业出版社,1999
4.Roger S.Pressman, Software Engineering, A practitioner’s Approach, Fourth Edition, 1997
|