2023年11月26日发(作者:)
版本自动更新程序及3种实现策略
C/S程序是基于客户端和服务器的,在客户机编译新版本后将文件发布
在更新服务器上。然后建立一个XML文件,该文件列举最新版本号和
所有文件及文件最后修改日期。如文件较多可以通过工具自动建立XML
文件。当某客户机运行程序后会自动下载这个XML文件,通过与本地机
器上的版本号匹配,如本机上的版本号比服务器上的要旧,通知客户机
运行更新程序。如用户更新了版本,将最新版本号写入配置文件,这样
方便下一次匹配。
通过可行性分析可以使用下面3种方案下载
1.局域网共享文件夹下载
/ip远程下载
3.通过Web方式下载。
方式1适合内部网络,功能简单,编程只需调用()就能
实现。如建立VPN网络,也可视为远程下载。我们只需在服务器上共
享一个文件夹并设定访问权限,然后将最新版本文件存放在这个目录。
升级程序直接从这个目录Copy文件即可。
方式2是通过基于tcp/ip 的Socket组件编程来实现,使用这个
机制必须有服务器监听程序。其简单设计思路是在服务器端启动
TcpListener监听客户端的Socket连接,当Client发送连接请求,
TcpListener捕获当前请求的Socket,并获取收到的数据(字符串,称为
命令)。然后由命令处理程序分析该字符串,如果字符串头部包含
GET_FILE标识则为下载文件请求。
例:客户机向服务器程序发送请求命
令:"GET_FILE|D:"。首先TcpListener捕获
当前请求的Socket.并接收到字符数据
"GET_FILE|D:",通过分析发现"GET_FILE"
标识符,表示下载文件请求.然后通过
le(file="D:")将文件传送给当
前Socket。客户端由()方法接收来自服务器
发送的文件。
方式3是通过.NetFramework提供的WebClient组件下载文件。
只需指定DownloadData()方法中参数address(url)。
通过上面的介绍,1,3方法最简单。Tcp/ip相对复杂。
下面讲解版本更新程序系统框架图
主窗体<->下载控制器<->XmlLoader关系图
图解:
frmUpgrader窗体内定义了一个下载控制器及2个TreeView控件.
当执行[检查更新],控制器调用当前下载器的DownloadServerXml()
方法从服务器下载文件。下载成功将文件交给
XmlLoader分析器,分析器创建XmlDocument对象。最后将XML
分析器作为FileView构造器参数创建FileView实例,分别调用
FileView的LoadTreeViewClient方法创建客户端文件清单的
TreeView及LoadTreeViewServer方法创建服务器端文件清单的
TreeView。TreeView的数据来源是两个Xml文件。
DownloadController 下载控制器,它负责建立下载策略及控制当前
下载器。
FileView对象实际是个TreeView生成器。它跟据Xml结构自动
生成TreeView.
XmlLoader分析器主要功能是分析服务器端及本地的XML文件
(和)。XmlLoader类图列
举了所有方法,从图中可以看出控制XmlDocument对象。通过
SingleNode方法查找某个指定的文件,然后
获取文件最后修改日期文件名等信息用于匹配。
IDownloader接口定义了所有下载器的方法,下面会详细讲解3
个下载器的实现策略。
FileInfo是文件的实体类,结构相当简单,只包含文件名,物理路
径及最后修改时间。
三种不同的下载器实现方案:
三种不同的下载器实现方案类及接口说明:
frmUpgrader: 主窗体
DownloadController:下载控制器,如上图所示,它是控制
IDownloader接口。
IDownloader: 下载器接口, 三种不同的下载器分别实现了这个接口
LAN_Downloader: 局域网复制文件下载器。
WebClient_Downloader: 广域网下载器,通过WebClient组件下载
文件。
TcpIp_Downloader: Tcp/ip下载器。需要运行Tcp/ip服务器提供下
载服务。
主窗体有[检查更新]及[开始更新]两个按钮。分别调用下载控制器
的CheckUpdate()及Download()方法。
下载控制器控制IDownloader接口,三种不同的下载器分别实现了这
个接口,通过对象多态原理,实际上是
下载控制器间接控制着实现IDownloader接口的所有下载器。我们可
以把DownloadController理解为桥接(Bridge)
或适配器(Adpater)。IDownloader接口实现了3种下载策略,这也
是策略模式的应用。
Tcp/IP下载器图解:
关于Tcp/IP下载这里有个案例
使用Tcp/Ip下载文件(图)
/bbs/html/090809_
Tcp/IP下载器需要有服务器程序支持,使用tcp/ip传送文件其简单设
计思路是在服务器端启动TcpListener监听客户端的Socket连接。当
Client发送连接请求,TcpListener捕获当前请求的Socket,并获取收
到的数据(字符串,称为命令)。然后由命令处理程序分析字符串,如果
字符串头部包含GET_FILE则为下载文件请求。
例:如客户机向服务器程序发送请
求:"GET_FILE|D:"。首先TcpListener捕获
当前请求的Socket,收到字符串,如果是下载文件请求就通过
le(file="D:PUBLISH
")将文件传送给当前Socket。在客户端由
()方法接收来自服务器发送的文件。
参考上图来理解如何实现:
UpgraderServer 是tcp/ip服务器的核心类。他控制TcpListener
对象,TcpListener负责监听客户端的Socket连接。
当有下载文件请求时就调用SendFile()方法将文件传送给当前连接的
Socket.
Stop()方法用来关闭服务器.
SendFile()方法用来发送文件
StartListening()方法用户启动监听程序。
TcpListener是监听程序,它负责监听客户端的Socket连接。如
有连接请求触发AccecptSocket方法。该方法返回当前请求的Socket
对象。
UpgraderClient是tcp/ip客户端的核心类。他控制TcpClient对
象, TcpClient对象负责监听来自服务器的请求。
DownloadFile()方法详解:
要明白客户端是如何接收文件,先要明白NetworkStream对象.
NetworkStream是提供用于网络访问的基础数据流。客户机监听来自
服务器的数据是通过()方法实现的,当程序执
行到()方法时就开始监听,同时中断下面代码执行,直到接收
到数据才会执行Read()下面的代码。请看代码。
byte[] resBytes = new byte[256]; //一次接收256字节
int resSize; //当前接收到的数据长度
do
{
//开始监听,同时中断下面代码执行,直到接收到数据才会执行Read()下面的代码。
resSize = (resBytes, 0, );
string msg = Byte2Str(resBytes);
if (().ToUpper() == "FILE_NOT_FOUND")
{
if (_writeOutput != null) _writeOutput("找不到文件:" + file);
break;
}
if (resSize == 0) break;
(resBytes, 0, resSize);
} while (ailable);
();
请注意while (ailable)这段代码,当接受到来自服务器的数
据时DataAvailable=True,然后通过方法每
次读取256字节,直到读取完所有数据时DataAvailable=false。这
时监听工作完成,跳出while循环。最后调用FileStream对象保存文
件。
TcpIp_Downloader Tcp/IP下载器方法
Download():下载定义的所有文件
DownloadFile(FileInfo file):下载单个文件
DownloadServerXml():下载服务器上的文件清单
Init() //初始化下载器
IDownloader下载器接口定义
///
/// 下载器接口
///
public interface IDownloader
{
void Init(); //初始化下载器
void Download();//下载所有文件
FileInfo DownloadFile(FileInfo file); //下载单个文件
XmlLoader XmlServer { get;} //服务器上的Xml文件
XmlLoader XmlLocal { get;}//客户机上的Xml文件
int DownloadsCount { get;} //下载成功的文件总数
int DownloadFaliedCount { get;}//下载失败的文件总数
void DownloadServerXml(); //下载服务器上的文件清单(xml文件)
void SetProgressBar(ToolStripProgressBar progress);
void SetTrace(ListBox logList);
}
下载器类型
///
/// 下载器类型
///
public enum DownloadType
{
Intranet = 1,
TcpIp = 2,
WebDownload = 3
}
下载控制器,该控件器可以创建3种不同的下载器。
///
/// 下载控制器,该控件器可以创建3种不同的下载器。
/// 策略模式应用。
///
public class DownloadController
{
private IDownloader _downloader = null;
public IDownloader CurrentDownloader { get { return _downloader; } }
private TreeView _tvServerFiles;
private TreeView _tvLocalFiles;
private ListBox _log;
private ToolStripProgressBar _progress = null;
public DownloadController(IDownloader downloader)
{
_downloader = downloader;
}
///
/// 跟据下载类型创建3种不同的下载策略
///
public static DownloadController Create(DownloadType type)
{
if (et == type)
return new DownloadController(new LAN_Downloader());
if ( == type)
return new DownloadController(new TcpIp_Downloader());
if (nload == type)
return new DownloadController(new WebClient_Downloader());
return null;
}
public void Download()
{
_("开始下载....");
_gressBar(_progress);
_();
_ce(_log);
_ad();
_("下载完成....");
_();
_ce(_log);
//加载Treeview
new FileView(_ver, _progress).LoadTreeViewServer(_tvServerFiles);
new FileView(_al, _progress).LoadTreeViewClient(_tvLocalFiles,
_ver);
if (_Version)
_("服务器上有最新版本,请更新.");
else
_("检查完成,没有发现新版本.");
}
public void BindControls(TreeView tvServerFiles, TreeView tvLocalFiles, ListBox log,
ToolStripProgressBar progress)
{
_progress = progress;
_tvLocalFiles = tvLocalFiles;
_tvServerFiles = tvServerFiles;
_log = log;
}
}
文件对象定义
///
/// 文件对象
///
public class FileInfo
{
private string _name = "";
private string _FullPath = "";
private DateTime _ModifyTime = ue;
this.FullPath = fullPath;
this.ModifyTime = lastEditDate;
}
///
/// 纯文件名,不包含路径。:如
///
public string Name { get { return _name; } set { _name = value; } }
///
/// 文件完整路径。如:[.]
///
public string FullPath { get { return _FullPath; } set { _FullPath = value; } }
///
/// 最后更新时间。
///
public DateTime ModifyTime { get { return _ModifyTime; } set { _ModifyTime = value; } }
public override string ToString()
{
return this.Name;
}
}
XML文件解释器,分析服务器/客户端的xml文件
using System;
using c;
using ;
using ;
using ;
using tions;
using ;
namespace graderLib
{
///
/// XML文件解释器,分析服务器/客户端文件清单。
///
public class XmlLoader
{
private XmlDocument _xml;
public XmlDocument XML { get { return _xml; } }
private string _xmlFilePath;
public XmlLoader(string xmlFile)
{
_xml = new XmlDocument();
_xmlFilePath = xmlFile;
if ((xmlFile)) _(xmlFile);
}
private bool _HasNewVersion = false;
//本机文件清单与服务器文件清单比较后是否发现新版本。
public bool HasNewVersion { get { return _HasNewVersion; } set { _HasNewVersion = value; } }
///
/// 创建空的Xml文件
///
///
public static XmlLoader CreateEmpty(string xmlFilePath)
{
string xml =
" rn" +
"
"
"
"
"
" rn" +
"
" rn" +
" rn";
//删除旧的更新文件
if ((xmlFilePath)) (xmlFilePath);
string dir = ectoryName(xmlFilePath);
if (!(dir)) throw new Exception("不存在目录:" + dir);
StreamWriter sw = Text(xmlFilePath);
(xml);
();
();
return new XmlLoader(xmlFilePath);
}
//保存最后更新信息
public void SetLastUpdateInfo(string version, DateTime lastUpdateTime)
{
XmlNode nodeVersion = _SingleNode("Upgrader/Application/Version");
XmlNode nodeTime = _SingleNode("Upgrader/Application/LastUpdateTime");
utes["value"].Value = version;
utes["value"].Value = ng();
}
//获取xml文件版本信息
public string GetVersion()
{
XmlNode ver = _SingleNode("Upgrader/Application/Version");
if (ver != null)
return utes["value"].Value;
else
return "";
}
///
/// 比较服务器与本机文件的最后更新时间。
/// 返回True:表示可以更新。False:服务器与本机文件版本一致。
///
/// 服务器上的文件
///
public bool CompareFile(FileInfo file)
{
if (file == null) return true; //文件没找到,为不相同,返回True;
XmlNode node = this.GetFileNode(th);
if (node == null) return true; //文件没找到,为不相同,返回True;
DateTime date;
if (se(utes["lastModify"].Value, out date))
{
return eTo(date) > 0;
}
return false;
}
///
/// 比较两个XmlNode的日期大小
///
public bool CompareNode(XmlNode node1, XmlNode node2)
{
if (node1 == null || node2 == null) return false;
DateTime date1 = ate(utes["lastModify"].Value);
DateTime date2 = ate(utes["lastModify"].Value);
return eTo(date2) > 0;
}
//获取在xml文件的结点
public XmlNode GetFileNode(string fullPath)
{
string xPath = @"Upgrader/Files/File[@fullPath=''" + fullPath + "'']";
XmlNode node = _SingleNode(xPath);
return node;
}
//获取在xml文件的结点,转换为FileInfo对象。
public FileInfo GetFileInfo(string fullPath)
{
XmlNode node = this.GetFileNode(fullPath);
if (node != null)
{
FileInfo fi = new FileInfo();
th = utes["fullPath"].Value;
Time = ate(utes["lastModify"].Value);
= utes["fileName"].Value;
return fi;
}
return null;
}
///
/// 在客户端的Xml记录文件加入更新记录
///
///
///
public void AddOrUpdateHistory(FileInfo serverFile, FileInfo clientFile)
{
XmlNode node = GetFileNode(th);
if (node == null)
{
XmlNode fileRoot = _SingleNode("Upgrader/Files");
node = _Node(t, "File", "");
Child(node);
}
All();//先删除结点内的数据
(CreateAttribute("fileName", ));
(CreateAttribute("fullPath", th));
(CreateAttribute("lastModify", ng()));
}
private XmlAttribute CreateAttribute(string name, string value)
{
XmlAttribute attr = _Attribute(name);
= value;
return attr;
}
//保存历史记录
public void Save()
{
_(_xmlFilePath);
}
///
/// 获取文件数量
///
public int FilesCount
{
get
{
XmlNode node = _SingleNode("Upgrader/Files");
return ;
{
FileInfo sf = new FileInfo();
th = utes["fullPath"].Value;
Time = ate(utes["lastModify"].Value);
= utes["fileName"].Value;
(sf);
}
return files;
}
}
}
版本自动更新程序及3种实现策略(一)文档及UML图
版本自动更新程序及3种实现策略(二)下载器实现
程序界面及系统设置
图1-版本升级程序服务器端设置
1. 服务器端程序发布URL地址,该参数用于Web下载器连接的url
地址。
2. 服务器端程序发布目录,用于tcp/ip下载器下载的目录。
3. 服务器端程序共享目录,用于Lan下载器下载的目录.
以前3个参数跟据选择的下载器类型做相应设置。
图2-本机配置
本地程序发布目录:用于任一下载器下载文件后存放文件的目录。
图3-下载器设置(更新参数设置,未改名)
选择三种下载器中任何一种作为当前下载器。
图4-Tcp/Ip下载器服务器程序.
当您选择Tcp/Ip下载器升级程序,请先运行服务器端程序。
图5-版本自动升级程序主界面
运行程序前先要配置系统参数,配置文件保存在程序运行目录下的
upgrader.dat文件。参考上面的所介绍的系统设置界面。跟据选择的
下载器类型作相应配置。
如出现以下提示,说明您还没有配置程序目录下无upgrader.dat
文件.
图6-没有配置文件提示窗体
服务器程序发布目录结构如下图:
图7-服务器程序发布目录结构
D:Shared是服务器上的目录,该目录存放最新版本文件及XmlSer
文件清单。
清单文件可以通过枚举目录下包括子目录下所有文件自动生成,下次更
新版本时只需调整某几项内容。
文件内容
version="1.0" encoding="utf-8" ?> 2009 9:53:23 AM" /> 53:23 AM" /> /> 09 9:53:23 AM" /> 6/2009 9:53:23 AM" /> /2009 9:53:23 AM" /> 9:53:23 AM" /> 26/2009 9:53:23 AM" /> rader.exe" lastModify="4/26/2009 9:53:23 AM" /> toUpgradeServer.exe" lastModify="4/26/2009 9:53:23 AM" /> " lastModify="4/26/2009 9:53:23 AM" /> 系统参数代码实现(序列化对象保存为文件) using System; using c; using ; using ; using ; namespace graderLib { /// /// 系统参数。序列化对象保存为文件. /// [Serializable] public class AppSettings { private string _ServerSharedFolder = ""; private string _ServerIP = ""; private int _ServerPort = 0; private string _ServerFilesXml = ""; private string _ServerPublishFolder = ""; //用于tcp/ip下载.服务器上程序文件的发布目录。 private string _ServerPublishUrl = ""; private string _ClientSaveFolder = ""; private string _ClientFilesXml = ""; private int _DownloaderType = 0; private static AppSettings _instance = null; /// /// 系统参数实例。 /// public static AppSettings Instance { get { if (_instance == null) CreateDefault(); return _instance; } } private static void CreateDefault() { _instance = new AppSettings(); _FilesXml = ""; _SharedFolder = @"192.168.1.2Shared"; _PublishUrl = "/UserUpload"; _PublishFolder = @"d:mypublishautoupgrader"; _IP = "192.168.1.1"; _Port = 12345; _aderType = (int)et; _FilesXml = ""; _SaveFolder = @"c:yourfoldernewversion"; } public static bool HasSetting() { string file = pPath + @"upgrader.dat"; return (file); } /// /// 读取参数 /// public static void Read() { string file = pPath + @"upgrader.dat"; if ((file)) { FileStream fs = (file, Create, ); byte[] bs = new byte[]; int len = (bs, 0, ); if (len > 0) { object o = ressionObject(bs); _instance = (AppSettings)o; } (); } } /// /// 保存参数 /// public static void Write() { string file = pPath + @"upgrader.dat"; FileStream fs = (file, Create, ); byte[] bs = ssionObject(_instance); (bs, 0, ); (); (); } /// /// 用于内部网络直接Copy的共享目录。 /// public string ServerSharedFolder { get { return _ServerSharedFolder; } set { _ServerSharedFold er = value; } } /// /// 用于Tcp/Ip下载的服务器IP。 /// public string ServerIP { get { return _ServerIP; } set { _ServerIP = value; } } /// /// 用于Tcp/Ip下载的服务器端口 /// public int ServerPort { get { return _ServerPort; } set { _ServerPort = value; } } /// /// 下载类型(策略) /// public int DownloaderType { get { return _DownloaderType; } set { _DownloaderType = value; } } /// /// 发布在服务器上的程序Url地址。如:/publish /// public string ServerPublishUrl { get { return _ServerPublishUrl; } set { _ServerPublishUrl = valu e; } } /// /// 用于tcp/ip下载.服务器上程序文件的发布目录 /// public string ServerPublishFolder { get { return _ServerPublishFolder; } set { _ServerPublishFold er = value; } } /// /// 客户端文件目录,下载文件保存的目录。如:c:myapp /// public string ClientSaveFolder { get { return _ClientSaveFolder; } set { _ClientSaveFolder = valu e; } } /// /// 客户机器上的文件列表 /// public string ClientFilesXml { get { return _ClientFilesXml; } set { _ClientFilesXml = value; } } /// /// 服务器上的文件列表 /// public string ServerFilesXml { get { return _ServerFilesXml; } set { _ServerFilesXml = value; } } } } using System; using c; using ; using ; using ; using ssion; namespace graderLib { public class Common { //字符转日期 public static DateTime StrToDate(string date) { DateTime ret = ue; if (se(date, out ret)) return ret; else return ue; } } /// /// 压缩解压object /// public class ZipObject { public static byte[] CompressionObject(object DataOriginal) { if (DataOriginal == null) return null; BinaryFormatter bFormatter = new BinaryFormatter(); MemoryStream mStream = new MemoryStream(); bFormatter.Serialize(mStream, DataOriginal); byte[] bytes = y(); MemoryStream oStream = new MemoryStream(); DeflateStream zipStream = new DeflateStream(oStream, ss); (bytes, 0, ); (); (); return y(); } public static object DecompressionObject(byte[] bytes) { if (bytes == null) return null; MemoryStream mStream = new MemoryStream(bytes); (0, ); DeflateStream unZipStream = new DeflateStream(mStream, ress, t rue); object dsResult = null; BinaryFormatter bFormatter = new BinaryFormatter(); dsResult = (object)bFormatter.Deserialize(unZipStream); return dsResult; } } } using System; using c; using ; using ; using ; using ing; namespace graderLib { /// /// 文件视图,文件结构以树形展示。 /// public class FileView { private XmlLoader _xml = null; private ToolStripProgressBar _progress = null; public FileView(XmlLoader xml, ToolStripProgressBar progress) { _xml = xml; _progress = progress; } //将xml转换为TreeView public void LoadTreeViewServer(TreeView treeView) { (); XmlNode node = _SingleNode("Upgrader/Files"); if (node == null) throw new Exception("找不到xml文件的Upgrader/Files结点!"); _m = + 1; _m = 1; _ = 1; foreach (XmlNode n in odes) { CreateNode(treeView, n, null); _++; } } //将xml转换为TreeView.同时与服务器匹配 public void LoadTreeViewClient(TreeView treeView, XmlLoader server) { (); XmlNode node = _SingleNode("Upgrader/Files"); if (node == null) throw new Exception("找不到xml文件的Upgrader/Files结点!"); _m = + 1; _m = 1; _ = 1; foreach (XmlNode n in odes) { CreateNode(treeView, n, server); _++; } //如果服务器的版本文件数量大于本地文件数量,视为有更新。 if (_Version == false && server != null && _ount < server.FilesCount) _Version = true; } private void CreateNode(TreeView treeView, XmlNode n, XmlLoader comparer) { //取参数n的Attributies["fullPath"].Value //如:Value="." 多级目录 string fullPath = utes["fullPath"].Value; string[] part = (new char[] { char.Parse(@"") }); TreeNode currNode = null; foreach (string p in part) { if (p == ".") continue;//当前目录,不处理 if ( > 3 && f(".") > 0) //文件 { TreeNode node = new TreeNode(p); if (comparer == null) ndex = 0; //文件 else { XmlNode node2 = comparer.GetFileNode(fullPath); if (_eNode(node2, n)) { ndex = 2; edImageIndex = 2; _Version = true; } else ndex = 0; } if (currNode == null) (node); //加入根结点 else (node);//加入子结点 return; } else //子目录 { TreeNode tempNode = FindNode(treeView, currNode, p); //查找当前目录 if (tempNode == null) //未找到结点.则创建结点 { TreeNode tmp = new TreeNode(p); ndex = 1;//子目录 if (currNode == null) (tmp); //创建根目录 else (tmp); //在当前目录创建子目录 currNode = tmp; } else currNode = tempNode; //保存当前目录,方便查找下一级 } } } //查找结点,此方法仅在CreateNode方法有效.为CreateNode方法的子方法。 private TreeNode FindNode(TreeView treeView, TreeNode currNode, string text) { if (currNode == null) //在根目录搜索 { foreach (TreeNode node in ) if (r() == r()) return node;//找到 } else //在当前目录搜索 { foreach (TreeNode node in ) if (r() == r()) return node;//找到 } return null; //未找到 } } } using System; using c; using ; using s; using ; using ; namespace graderLib { /// /// Tcp/ip下载器客户端 /// public class UpgraderClient { private OutputInvoke _writeOutput = null; public UpgraderClient(OutputInvoke writeOutput) { _writeOutput = writeOutput; } private TcpClient _Client = null; private TcpClient Client { get { if (_Client == null) { _Client = new TcpClient(); } return _Client; } } public void CloseClient() { if (_Client != null && _ted) _(); } /// /// 下载文件 /// public bool DownloadFile(string file, string savePath) { try { TcpClient client = new TcpClient(); //eTimeout = 1000 * 60; if (client == null || () == "") return false; TryConnect(client, IP, Port); //连接服 务器 if (!ted) return false;//连线线失败,退出 byte[] bs = es("GET_FILE|" + file); (bs); //发送请求 //开始接受数据.... NetworkStream ns = eam(); MemoryStream ms = new Stream(); byte[] resBytes = new byte[256]; //一次接收256字节 int resSize; //当前接收到的数据长度 do { //开始监听,同时中断下面代码执行,直到接收到数据才会执行Read()下面的代码。 resSize = (resBytes, 0, ); string msg = Byte2Str(resBytes); if (().ToUpper() == "FILE_NOT_FOUND") { if (_writeOutput != null) _writeOutput("找不到文件:" + file); break; } if (resSize == 0) break; (resBytes, 0, resSize); } while (ailable); (); //关闭网络数据流 if ( > 0) { FileStream fs = (savePath, Create, ); (y(), 0, (int)); (); (); //关闭文件流 if (_writeOutput != null) _writeOutput("文件已下载:" + file); } (); //关闭内存流 ();//关闭网络套接 return true; } catch { return false; } } private string Byte2Str(byte[] buffer) { string msg = ing(buffer).Replace("0", ""); return (); } private void TryConnect(TcpClient client, string hostIP, int hostPort) { try { t((hostIP), hostPort); //连接服务器 } catch { throw new Exception("主机已关闭或网络存在问题,不能建立连线!"); } } } } UpgraderServer.cs using System; using c; using ; using s; using ing; using ; using ; using ; namespace graderLib { //跨线程调用控件显示消息 public delegate void OutputInvoke(string msg); /// /// tcp/ip下载器服务器 /// public class UpgraderServer { private TcpListener _ServerListener = null; //本地消息监听器 private Thread _ServerListenerThread = null; //监听器使用的线程 private bool _ServerRunning = false; private Form _owner = null; private OutputInvoke _writeOutput = null; public UpgraderServer(Form owner, OutputInvoke method) { _owner = owner; _writeOutput = method; } //启动聊天服务器程序. 参数说明 ip:本地消息服务器IP地址; port:端口 public void StartListening(string ip, int port) { if (_ServerRunning) return; //构建监听器 _ServerListener = new TcpListener((ip), port); _ServerListener.Start(255); _ServerRunning = true; //启动线程 _ServerListenerThread = new Thread(new ThreadStart(DoStartServerListener)); _ground = true; _(); } //关闭聊天服务器程序. public void Stop() { _ServerRunning = false; _(101); _ServerListenerThread = null; _ServerListener.Stop(); } /// ///启动服务器程序. /// private void DoStartServerListener() { //监听客户连线请求 while (_ServerRunning) { try { if (_ServerListener == null) return; //防止其它地方关闭监听器 ts(); Socket socket = _ServerListener.AcceptSocket(); //有客户请求连接 if (socket == null) continue; byte[] buffer = new Byte[eBufferSize]; int i = e(buffer); //接收请求数据. if (i <= 0) continue; string msg = ing(buffer).Replace("0", ""); msg = (); if (r().StartsWith("GET_FILE")) //命令字符串:GET_FILE|. { string[] sps = (new char[] { char.Parse("|") }); string file = sps[1]; //取出文件 this.SendFile(socket, file); } ();// } catch (Exception ex) { if (ex is ThreadAbortException) { if ((ex as ThreadAbortException).ng() == "101") { _ServerRunning = false; ShowLog("用户关闭服务器."); } else ShowLog(e); } else { ShowLog(e); } } } } private void SendFile(Socket socket, string file) { if ((file)) { ShowLog("获取文件[" + file + "]...."); le(file); ShowLog("[" + file + "]已发送."); } else { (es("FILE_NOT_FOUND")); //通知客户程序 ShowLog("[" + file + "]不存在."); } } //在_ServerListener线程内操作主线程上的控件。 private void ShowLog(string log) { //访问其它线程上的控件,需要用Invoke方法 _owner.Invoke(_writeOutput, log); } }


发布评论