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窗体内定义了一个下载控制器及2TreeView控件.

当执行[检查更新],控制器调用当前下载器的DownloadServerXml()

方法从服务器下载文件。下载成功将文件交给

XmlLoader分析器,分析器创建XmlDocument对象。最后将XML

分析器作为FileView构造器参数创建FileView实例,分别调用

FileViewLoadTreeViewClient方法创建客户端文件清单的

TreeViewLoadTreeViewServer方法创建服务器端文件清单的

TreeViewTreeView的数据来源是两个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

对象。

UpgraderClienttcp/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" +

" rn" +

" rn" +

" 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" ?>

服务器端文件清单

value="4/26/2007 10:30:32 AM" />

value="1.2.1" />

fullPath="." fileName="" lastModify="4/26/

2009 9:53:23 AM" />

fullPath=".ip_" fileName="ip_" lastModify="4/26/2009 9:

53:23 AM" />

fullPath="." fileName="" lastModify="4/26/2009 9:53:23 AM"

/>

fullPath="." fileName="" lastModify="4/26/20

09 9:53:23 AM" />

fullPath=".KAV8.0-Key.R00" fileName="KAV8.0-Key.R00" lastModify="4/2

6/2009 9:53:23 AM" />

fullPath="." fileName="" lastModify="4/26

/2009 9:53:23 AM" />

fullPath="." fileName="" lastModify="4/26/2009

9:53:23 AM" />

fullPath="." fileName="" lastModify="4/

26/2009 9:53:23 AM" />

fullPath=".grader.exe" fileName="g

rader.exe" lastModify="4/26/2009 9:53:23 AM" />

fullPath=".gradeServer.exe" fileName="

toUpgradeServer.exe" lastModify="4/26/2009 9:53:23 AM" />

fullPath="." fileName="

" 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)

{

//取参数nAttributies["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);

}

}