📄 formupdate.cs
字号:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using IMLibrary;
using System.Reflection;
namespace LanMsg
{
public partial class FormUpdate : Form
{
public FormUpdate()
{
InitializeComponent();
this.BeginListen();
}
#region 变量区域
/// <summary>
/// 升级文件的大小
/// </summary>
public int fileLen;
/// <summary>
/// 升级服务器的IP地址
/// </summary>
public System.Net.IPAddress serverIp = System.Net.IPAddress.Parse("127.0.0.1");
/// <summary>
/// 升级服务器的端口号
/// </summary>
public int serverPort = 5678;
/// <summary>
/// 当前下载文件的大小
/// </summary>
public int currLen;
/// <summary>
///
/// </summary>
public byte[] buf;
#endregion
private void sockUDP1_DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port)
{
DataArrivaldelegate outdelegate = new DataArrivaldelegate(DataArrival);
this.BeginInvoke(outdelegate, new object[] { Data, Ip, Port });
}
#region 数据达到事件处理过程DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port)
private delegate void DataArrivaldelegate(byte[] Data, System.Net.IPAddress Ip, int Port);
private void DataArrival(byte[] Data, System.Net.IPAddress Ip, int Port)
{
int cnt = 0;//记录接收到的数据包大小
cnt = Data.Length;//获取接收到的数据包大小
if (cnt < 3) return;//如果收到的数据小于3个字节则视为非法用户,抛弃
if (Data[0] != 255) return;//将非法用户的数据抛弃
try
{
byte[] buffer = new byte[cnt - 2];//申明一个字节数组,用于保存去除第一个字节码(即LanMsg协议编码)的其它数据(即消息实体)
Buffer.BlockCopy(Data, 2, buffer, 0, cnt - 2);//去除前两个字节码(即LanMsg协议编码)的其它数据为消息实体,将其保存于Buffer字节数组
switch (Data[1])// 取得第一个字节码,即LanMsg协议编码,根据编码判断用户发过来的请求为何种类型
{
case 0://服务器通知有新版本的LanMsg
break;
case 1:// 收到服务器发送过来的文件块
this.ReceivedFileBlock(new IMLibrary.DataArrivalEventArgs(buffer, Ip, Port));
break;
case 2://服务器通知有新版本,并返回升级包文件大小
this.getFileLen(new IMLibrary.DataArrivalEventArgs(buffer, Ip, Port));
break;
}
}
catch
{ }
}
#endregion
#region 获得服务器提供的升级包大小
/// <summary>
/// 获得服务器提供的升级包大小
/// </summary>
/// <param name="e"></param>
private void getFileLen(DataArrivalEventArgs e)
{
try
{
int len = IMLibrary.TextEncoder.bytesToInt(e.Data);
this.fileLen = len;
this.xpProgressBar1.PositionMax = this.fileLen;
//MessageBox.Show("获取文件大小:" + len.ToString(), "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
this.getUpdateFileData();
}
catch(Exception x)
{
MessageBox.Show("获取文件大小失败!"+ x.Source +":"+ x.Message ,"提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
}
}
#endregion
#region 处理对方发送文件数据块
private delegate void ReceivedFileBlockdelegate(IMLibrary.sendFileInfo msg);
/// <summary>
/// 处理对方发送文件数据块
/// </summary>
private void ReceivedFileBlock(IMLibrary.DataArrivalEventArgs e)//当对方发送文件数据块过来
{
IMLibrary.sendFileInfo msg = IMLibrary.Serializers.ByteToObj(e.Data) as IMLibrary.sendFileInfo;
if (msg == null) return;
if (msg.pSendPos > this.currLen)
{
this.buf = new byte[msg.FileBlock.Length ];
this.buf = msg.FileBlock;
this.currLen = msg.pSendPos;
}
}
#endregion
#region 获得更新文件的全部数据
/// <summary>
/// 获得更新文件的全部数据
/// </summary>
private void getUpdateFileData()
{
int lastLen=this.currLen;//临时记录上一次发送的位置
bool isFirstSend=true ;//是否第一次向服务器请求
System.DateTime tempTime=System.DateTime.Now;//当前时间
System.IO.FileStream fStream = new System.IO.FileStream(Application.StartupPath + @"\LanMsgUpdate.exe", System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.Read);
while (this.currLen != this.fileLen)//当文件没有下载完成
{
Application.DoEvents();
if (this.currLen > lastLen || isFirstSend)//如果是第一次下载请求或上一次请求已经收到返回数据,则继续请求,直到文件下载完成
{
lastLen = this.currLen;//更改上一次获得的数据位置
this.xpProgressBar1.Position = this.currLen;
//写文件
if (!isFirstSend)//如果不是第一次发请求下载
{
fStream.Write(this.buf, 0, this.buf.Length);//将收到的文件块存于文件中
fStream.Flush();
}
//发下一次请求
sendMsgToOneUser(1, IMLibrary.TextEncoder.intToBytes(this.currLen));
isFirstSend = false ; //标记非第一次下载
}
if (lastLen == this.currLen && this.DateDiff(tempTime, System.DateTime.Now) > 2)//如果已经超时2秒,则重新发送上次的数据包
sendMsgToOneUser(1, IMLibrary.TextEncoder.intToBytes(this.currLen));
}
fStream.Close();
MessageBox.Show("文件下载成功");
}
#endregion
#region 发送消息给一个用户sendMsgToOneUser(Byte msgInfo ,byte[] msgContentn)
/// <summary>
/// 发送消息给一个用户
/// </summary>
/// <param name="msgInfo">消息类型</param>
/// <param name="msgContent">消息内容</param>
/// <param name="Ip">接收者IP</param>
/// <param name="Port">接收者端口</param>
public void sendMsgToOneUser(Byte msgInfo, byte[] msgContent)//给一个用户发送消息
{
byte[] buf = new byte[msgContent.Length + 2];
buf[0] = 255;//合法用户标识
buf[1] = msgInfo;//消息类型
Buffer.BlockCopy(msgContent, 0, buf, 2, msgContent.Length);
this.sockUDP1.Send(this.serverIp,this.serverPort,buf);
}
#endregion
#region 计算时间差
/// <summary>
/// 计算时间差
/// </summary>
/// <param name="DateTime1">开始时间</param>
/// <param name="DateTime2">结束时间</param>
/// <returns></returns>
private int DateDiff(DateTime DateTime1, DateTime DateTime2)
{
int dateDiff = 0;
try
{
TimeSpan ts1 = new TimeSpan(DateTime1.Ticks);
TimeSpan ts2 = new TimeSpan(DateTime2.Ticks);
dateDiff = ts2.Subtract(ts1).Seconds;
}
catch
{ }
return dateDiff;
}
#endregion
#region 选择服务端口并开始侦听服务BeginListen()
/// <summary>
/// 选择服务端口并开始侦听服务
/// </summary>
private void BeginListen()
{
System.Random i = new Random();
resetPort:
int j = i.Next(2000, 60000);//端口取值范围
try
{
this.sockUDP1.Listen(j);//UDP开始侦听来自外部的消息
}
catch
{
goto resetPort;
}
}
#endregion
private void FormUpdate_Load(object sender, EventArgs e)
{
this.BeginListen();// 选择服务端口并开始侦听服务
byte[] buf = IMLibrary.TextEncoder.textToBytes(Assembly.GetExecutingAssembly().GetName().Version.ToString());
this.sendMsgToOneUser(0, buf);//向服务器发送当前文件版本号
}
private void buttonX1_Click(object sender, EventArgs e)
{
this.sockUDP1.CloseSock();
this.Close();
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -