时榕茂
(上海船舶运输科学研究所,上海 200120)
船舶监测系统主要用于对全船各机电设备实现各种重要参数的测量和超限报警等,同时具有对各种重要设备进行远程集中控制、区域监控,对空压冷水机等进行健康管理及数据采集处理等功能,是一个控制测量、安全保护以及管理一体化的系统,主要安装在集控台。在实际生产运行过程中由于计算机台数比较多且比较分散,当系统需要升级时,需要船上工作人员花费大量的时间在不同的地点、不同的计算机设备上进行逐个手工升级操作,这大大降低了工作效率。
随着计算机技术的不断发展,对于软件系统交付给客户之后的维护升级工作,也是一项非常重要的环节,功能需求的变化或提升往往需要对系统进行升级维护。当前船舶监测系统主要采用C/S架构,随着软件的推广和用户的增多,此架构的软件系统升级维护工作一直是困扰工作人员的主要难点。以往的升级维护操作手段通常采用人工手动升级,由工作人员将需要更新的文件放入移动硬盘中,通过手工复制到运行文件夹中进行升级操作。由于电脑比较分散,工作人员需要对多台电脑在不同地点进行重复安装。这种操作方法,在实际应用中不仅需要耗费大量的精力和时间,而且容易造成在升级过程中的一些操作不当引起的功能不全或其他错误,对客户的使用安全造成不利的影响,存在安全隐患。
软件维护是软件整个生命周期的不可或缺的重要环节[1]。基于传统的人工手动升级操作方式的自动化效率太低,为了改善应用软件的可靠性和可适应性,实现软件系统的自动升级就显得尤为必要。为解决此问题在实际生产中带来的困扰,本文主要阐述实现船舶监测系统的自动更新方法和实现过程,并在实际生产中取得了非常好的使用效果。
软件自动升级的原理,主要涉及两个程序,一个是主程序(即船舶监测系统,简称F22P.exe),一个是升级程序(主要用于软件自动升级,简称update.exe)。所有的版本更新升级均由升级程序完成。首先计算机开机后,升级程序自动启动,升级程序启动后通过协议读取服务器中update.xml配置文件中的版本号,然后与客户端的程序版本号信息进行比较,如果版本号一致或客户端版本号大于服务器中的文件版本号不需要进行自动升级,反之,则需要对程序进行更新,图1为船舶监测系统自动升级的流程图。
图1 船舶监测系统自动升级流程
如果客户端程序需要更新,对其进行更新的详细步骤如下:
(1)从服务端通过动态链接库中的动态数组获取需要下载更新的文件列表,下载文件列表到客户端指定的临时文件夹;
(2)检查临时文件夹中下载的文件是否为客户端主程序更新所需的文件;
(3)检查主程序是否启动运行,如果运行则关闭主程序,或者主程序未运行但是主程序进程在运行,则关闭进程;
(4)备份主程序中的文件,将临时文件夹中的所有文件替换到指定主程序的文件夹位置,覆盖替换更新主程序文件;
(5)更新客户端主程序文件中的版本号信息(主程序文件记录在Version.txt中);
(6)关闭升级程序,完成升级;
(7)重新启动主程序。
在服务器上创建FTP服务站点,打开FTP服务的端口号,采用FTP传输协议,客户端向服务器端发送连接,通过同时打开并监听同一打开的端口号建立数据连接,采用socket通信原理完成服务端和客户端的通信,服务端的功能主要包含:软件自动升级检测系统的更新文件包、自动升级程序客户端管理,其中更新软件包中包含update.xml配置文件和需要更新升级的所有文件;自动升级程序客户端管理主要记录客户端已经升级的电脑和应该升级而暂未升级的电脑,对于应该升级而未升级的客户端则不断提示需要升级。
用户在客户端安装船舶监测系统软件后,在主程序安装目录下包含:主程序.exe、Version.txt(主要记录版本信息)、lib文件夹(静态库,动态库dll文件)、DATA文件夹(数据库、各种图元信息)、record文件夹(记录日志文件)。
文件下载主要通过FTP文件传输协议,每次客户端升级程序提出一个请求,服务器与客户端通过控制连接相同的端口号建立一个数据连接,通过Socket实现文件的下载功能,通过downLoad⁃File()方法下载文件,下面是此方法的部分代码。
FileStream output=new FileStream(‘本地文件名’,FileMode.Open);
Socket csocket=createDataSocket();//数据连接Socket
long offset=0;
offset=output.Length;
if(offset>0)
{
sendCommand("REST"+offset);
}
long npos=output.Seek(offset,SeekOrigin.Begin);
sendCommand("RETR"+remFileName);
while(true)
{
bytes=csocket.Receive(buffer,buffer.Length,0);
//接收指定的字节数存入缓冲区的位置
output.Write(buffer,0,bytes);//输出内容
if(bytes<=0)
{
break;
}
}
output.Close();
if(csocket.Connected)
{
csocket.Close(); //关闭数据连接
}
将升级文件替换到主程序文件之前,需要先将主程序文件备份到一个指定文件夹,可以更好地进行系统版本的管理。对主程序进行备份的主要步骤,首先遍历主程序文件中所有的文件,把遍历的文件存放在一个数组中,然后把所有的文件复制到备份文件中。
文件下载完毕后,自动升级文件需要更新替换主程序文件,如果主程序文件正在运行,则不能进行替换,必须先关闭主程序,升级程序首先遍历找到该主程序进程,然后强制关闭该进程,主程序退出。
升级文件完成对主程序文件的更新替换后,需要对主程序进行重新启动,这些操作需要升级程序执行外部程序,本升级系统主要通过函数调用的方式打开主程序,可供参考的此类函数有很多个,本系统主要采用process.start()方式。
服务器端软件配置文件update.xml,主要用来记录程序的版本信息、软件名称、文件的更新日期、是否需要重新启动应用系统程序和需要重新启动的主程序名称。升级程序通过FTP协议从服务端获取文件的最新的版本信息,与当下客户端主程序的版本信息进行比较,若客户端的当前应用版本号小于服务端版本号,则系统弹出提示框提示用户软件需要升级(图2),点击确定按钮,则软件升级程序根据协议,对服务器端的更新文件全部下载,下载更新后,重新启动主程序。以下是服务端update.xml配置文件的配置信息。
图2 系统更新提示
//需要升级的文件更新日期
//需要升级的程序版本号
//需要重新启动的程序名称
通过方法读取服务端的版本信息和客户端的版本信息,以下是读取服务端的版本信息代码。
//获取服务器端程序的版本号
WebClient wc=new WebClient();
Stream stream=wc.OpenRead(updateUrl);
XmlDocument xmlDoc=new XmlDocument();
xml Doc.Load(stream);//读取XML配置文件
XmlNode list=xmlDoc.SelectSingleNode("Update");
foreach(XmlNode node in list)
{
if(node.Name=="Soft"&&node.Attributes["Name"].Value.ToLower()==SoftName.ToLower())
{
foreach(XmlNode xml in node)
{
if(xml.Name=="Verson")
newVerson=xml.InnerText;//读取版本号
else
download=xml.InnerText;
}
}
}
以下是读取客户端的版本信息,读取客户端程序的版本号,客户端版本号记录在Version.txt文档中,通过StreamReader读取文档中的版本号信息。
StreamReader sr=new StreamReader(path,Encoding.Default);
stringver=sr.ReadLine();//读取文档中的版本号
//检查是否需要更新
int tm=verso.CompareTo(newVerson);
//比较客户端版本号和服务器文件版本号
if(tm>=0)
isUpdate=false;
else
isUpdate=true;//执行更新程序
对客户端和服务端的版本信息进行比较,如果客户端版本信息大于服务端版本信息,则不进行更新,反之则在客户端界面弹出提示框,提醒用户有新的版本信息需要进行更新,点击确定按钮,更新程序利用FTP传输协议将需要更新的文件从服务器下载到本地指定的临时文件夹下,然后,更新程序对已经下载的文件进行检验,确保所下载文件属于主程序升级所需要文件;最后完成文件替换,首先将待更新文件打包备份到指定文件位置,然后将临时文件夹中的文件移动到主程序所在目录下覆盖更新,同时更新客户端的主程序版本信息与服务器中的版本信息一致,重新启动主程序即完成升级工作。
本文根据网络协议、配置文件、C/S架构等技术,通过比较客户端系统版本号和服务端文件版本号,实现船舶监测系统的自动升级工作。自动升级系统的使用既节约大量的人员,也减少了船上工作人员的工作量,提高了工作效率,目前取得了较好的使用效果。与传统的系统升级技术相比,本文所描述的自动升级系统具有成本低廉、出错率低、效率高等特点,具有很高的生产使用价值,并且对系统采用版本控制的集中管理方式,使系统具有更好的可维护性,为研究其他船舶软件的升级维护提供参考价值。