You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1336 lines
50 KiB
C#

2 months ago
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NetLibrary.Network;
using System.Collections;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using NetLibrary.Log;
using System.IO;
namespace NetLibrary.Network
{
#region 服务器Socket
public class SocketService
{
/// <summary>
/// 要监控的端口号
/// </summary>
public int Port { get; set; }
/// <summary>
/// 空闲超时自动断开或引发心跳包事件
/// </summary>
public int OutTime { get; set; }
/// <summary>
/// 重发等待默认30秒后重发
/// </summary>
public int RefshSecond { get; set; }
/// <summary>
/// 最大消息等待回包数量(滑动窗口)
/// </summary>
public int MaxWaitMsgNumber { get; set; }
public AddressFamily Family { get; set; }
public int MaxSendNumber { get; set; }
public int BufferSize { get; set; }
public bool OutMaxSendNumberCloseConnect { get; set; }
/// <summary>
/// 是否长连接(默认长连接)
/// </summary>
public bool IsLongConnect { get; set; }
/// <summary>
/// 是否启用发送线程
/// </summary>
public bool IsSendThread { get; set; }
/// <summary>
/// 数据读取到时发生
/// </summary>
public event Action<ServerConnection, DataEventArgs> ReceiveData;
/// <summary>
/// 连接完成时发生
/// </summary>
public event Action<ServerConnection> ConnectSocketComplete;
/// <summary>
/// 关闭时发生
/// </summary>
public event Action<ServerConnection> CloseSocketComplete;
/// <summary>
/// 心跳请求事件
/// </summary>
public event Action<ServerConnection> OutTimeHappen;
/// <summary>
/// 发送失败事件
/// </summary>
public event Action<SocketMessage> SendError;
public event Action<ServerConnection> ReadDataMessage;
TcpSocketListener socketListener = null;
public ServerConnectionPool ListUserSocket = new ServerConnectionPool();
private AutoResetEvent AutoReset = new AutoResetEvent(false);
public SocketArgsPool socketArgsPool = null;
//BufferPool bufferManager = null;
public bool IsRun = false;
public SocketService()
{
Family = AddressFamily.InterNetwork;
IsSendThread = false;
IsLongConnect = false;
OutTime = 180;
Port = 10000;
RefshSecond = 30;
MaxWaitMsgNumber = 10;
BufferSize = 1024;
OutMaxSendNumberCloseConnect = false;
}
#region 初始化缓存
public void Init()
{
//初始化数据接收缓存
//bufferManager = new BufferPool(MaxConnect * BuffSize, BuffSize);
//bufferManager.InitBuffer();
// 声明异步Socket
//SocketAsyncEventArgs readWriteEventArg;
//for (int i = 0; i < MaxConnect; i++)
//{
// //初始化异步Socket
// readWriteEventArg = new SocketAsyncEventArgs();
// // 设备接收数据缓存
// bufferManager.SetBuffer(readWriteEventArg);
// // 把异步Socket放入集合顶部
// socketArgsPool.CheckIn(readWriteEventArg);
//}
}
#endregion
#region 开始监控
public void Start()
{
socketArgsPool = new SocketArgsPool();
socketListener = new TcpSocketListener(Family, IPAddress.Any, Port, 10);
socketListener.SocketConnected += socketListener_SocketConnected;
socketListener.Start();
RunWhileListUserSocket();
}
#endregion
#region 结束监控
public void Stop()
{
IsRun = false;
AutoReset.Set();
socketListener.Stop();
while (true)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
model.Disconnect();
}
ListUserSocket.Clear();
System.GC.Collect();
}
#endregion
#region 结束监控并且发送断开连接消息
public void Stop(byte[] bytes)
{
IsRun = false;
AutoReset.Set();
socketListener.Stop();
while (true)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (bytes != null && bytes.Length > 0) model.SendData(bytes, 0, bytes.Length);
model.Disconnect();
}
ListUserSocket.Clear();
System.GC.Collect();
}
#endregion
#region 启动发送线程
void RunWhileListUserSocket()
{
if (this.IsSendThread == true)
{
Thread t1 = new Thread(new ThreadStart(this.WhileListUserSocket));
t1.Start();
}
else
{
Thread t1 = new Thread(new ThreadStart(this.WhileListUserSocket2));
t1.Start();
}
}
#endregion
#region 关闭设备连接
public bool CloseDevice(string IpAddress)
{
bool bk = false;
int index = ListUserSocket.Available;
for (int i = 0; i < index; i++)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (model.IpAddress == IpAddress)
{
model.Disconnect();
bk = true;
break;
}
ListUserSocket.CheckIn(model);
}
return bk;
}
#endregion
#region 关闭设备连接
public bool CloseDevice2(string DeviceNo)
{
bool bk = false;
int index = ListUserSocket.Available;
for (int i = 0; i < index; i++)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (model.DeviceNo == DeviceNo)
{
model.Disconnect();
bk = true;
break;
}
ListUserSocket.CheckIn(model);
}
return bk;
}
#endregion
#region 关闭设备连接
public bool CloseDevice3(string DeviceNo, int Port)
{
bool bk = false;
int index = ListUserSocket.Available;
for (int i = 0; i < index; i++)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (model.DeviceNo == DeviceNo && model.Port == Port)
{
model.Disconnect();
bk = true;
break;
}
ListUserSocket.CheckIn(model);
}
return bk;
}
#endregion
#region 接受连接请求
void socketListener_SocketConnected(object sender, SocketEventArgs e)
{
try
{
e.Socket.SendBufferSize = 32 * 1024;
e.Socket.ReceiveBufferSize = 32 * 1024;
e.Socket.LingerState = new LingerOption(true, 0);
e.Socket.SendTimeout = 60000;
//SocketAsyncEventArgs args = socketArgsPool.CheckOut();
SocketAsyncEventArgs args = null;
if (args == null)
{
args = new SocketAsyncEventArgs();
byte[] buffer = new byte[BufferSize];
args.SetBuffer(buffer, 0, buffer.Length);
}
ServerConnection connection = null;
try
{
connection = new ServerConnection(e.Socket, args);
connection.DataReceived += DataReceived;
connection.CloseSocketed += Disconnected;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
e.Socket.Close();
//if (connection!=null) connection.Disconnect();
return;
}
ListUserSocket.CheckIn(connection);
if (this.ConnectSocketComplete != null) this.ConnectSocketComplete(connection);
}
catch (Exception exx)
{
ErrorFollow.TraceWrite(exx.TargetSite.Name, exx.StackTrace, exx.Message);
}
}
#endregion
#region 读取消息
void DataReceived(ServerConnection sender, DataEventArgs e)
{
if (e.Data.Length == 0) return;
sender.PrevTime = DateTime.Now;
if (this.ReceiveData != null) this.ReceiveData(sender, e);
}
#endregion
#region 对方关闭连接
void Disconnected(ServerConnection model, SocketAsyncEventArgs e)
{
if (model == null || model.Enabled == false)
{
if (model != null)
{
model.DataReceived -= DataReceived;
model.CloseSocketed -= Disconnected;
}
if (this.CloseSocketComplete != null) this.CloseSocketComplete(model);
e.Dispose();
e = null;
model = null;
}
else
{
model.Disconnect();
}
}
#endregion
#region 发送完成时
void connection_SendCompleted(ServerConnection model)
{
if (this.IsRun == true) ListUserSocket.CheckIn(model);
}
#endregion
#region 轮循连接列表
void WhileListUserSocket()
{
//bool IsRemoveMessage = false;
IsRun = true;
while (IsRun)
{
try
{
ServerConnection model = ListUserSocket.CheckOut();
if (model == null)
{
AutoReset.WaitOne(5000, false);
continue;
}
if (model.Enabled == false) continue;
if (model.PrevTime.AddSeconds(this.OutTime) < DateTime.Now)
{
if (this.IsLongConnect == false)
{
ErrorFollow.TraceWrite("服务器检测到" + model.DeviceNo + "无应答", "", "断开对方连接");
model.Disconnect();
continue;
}
else
{
//如果是长连接引发,心跳事件
if (this.OutTimeHappen != null)
{
this.OutTimeHappen(model);
model.PrevTime = DateTime.Now;
ListUserSocket.CheckIn(model);
continue;
}
}
}
//如果服务器是断开连接的,那么不读取主动发送的数据
if (string.IsNullOrEmpty(model.DeviceNo) == false && model.ListMessage.Count == 0)
{
if (this.ReadDataMessage != null) this.ReadDataMessage(model);
}
if (model.ListMessage.Count > 0)
{
while (model.WaitMsgNumber < this.MaxWaitMsgNumber)
{
SocketMessage Msg = model.GetNextSocketMessage(this.RefshSecond);
if (Msg == null) break;
if (this.MaxSendNumber > 0 && Msg.SendNumber > this.MaxSendNumber)
{
if (OutMaxSendNumberCloseConnect == false)
{
model.EndWaitMsg(Msg.SequenceID);
continue;
}
else
{
model.Disconnect();
break;
}
}
if (this.Send(model, Msg) == false)
{
if (this.SendError != null) this.SendError(Msg);
break;
}
}
}
if (model.Enabled == false) continue;
if (model.ListMessage.IsEmployMessages == true) model.ListMessage.RemoveEmploy();
ListUserSocket.CheckIn(model);
AutoReset.WaitOne(10, false);
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
}
#endregion
#region 轮循连接列表
void WhileListUserSocket2()
{
IsRun = true;
while (IsRun)
{
try
{
ServerConnection model = ListUserSocket.CheckOut();
if (model == null)
{
AutoReset.WaitOne(30000, false);
continue;
}
if (model.Enabled == false) continue;
if (model.PrevTime.AddSeconds(this.OutTime) < DateTime.Now)
{
if (this.IsLongConnect == false)
{
ErrorFollow.TraceWrite("服务器检测到" + model.DeviceNo + "无应答", "", "断开对方连接");
model.Disconnect();
continue;
}
else
{
//如果是长连接引发,心跳事件
if (this.OutTimeHappen != null)
{
this.OutTimeHappen(model);
model.PrevTime = DateTime.Now;
ListUserSocket.CheckIn(model);
continue;
}
}
}
if (model.Enabled == false) continue;
ListUserSocket.CheckIn(model);
AutoReset.WaitOne(100, false);
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
}
#endregion
#region 发送数据
public bool Send(ServerConnection model, SocketMessage msg)
{
model.PrevTime = DateTime.Now;
try
{
msg.SendNumber++;
msg.SendTime = DateTime.Now;
bool bk = model.SendData(msg.Bytes, 0, msg.SendLength);
if (bk == false)
{
ErrorFollow.TraceWrite("Send", "", "发送失败断开连接");
model.Disconnect();
return false;
}
if (msg.IsRevert == false)
{
EndWaitMsg(model, msg.SequenceID);
}
else
{
if (msg.SendNumber > 1) model.IncrementWaitMsgNumber();
}
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
model.Disconnect();
return false;
}
return true;
}
#endregion
#region 返回UserSocket
public ServerConnection GetUserSocket(string IpAddress)
{
int index = ListUserSocket.Available;
for (int i = 0; i < index; i++)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (model.Enabled == false) continue;
if (model.IpAddress == IpAddress) return model;
ListUserSocket.CheckIn(model);
}
return null;
}
#endregion
#region 返回UserSocket
public ServerConnection GetUserSocket2(string DeviceNo)
{
int index = ListUserSocket.Available;
for (int i = 0; i < index; i++)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (model.Enabled == false) continue;
if (model.DeviceNo == DeviceNo) return model;
ListUserSocket.CheckIn(model);
}
return null;
}
#endregion
#region 返回UserSocket
public ServerConnection GetUserSocket3(string DeviceNo, int Port)
{
int index = ListUserSocket.Available;
for (int i = 0; i < index; i++)
{
var model = ListUserSocket.CheckOut();
if (model == null) break;
if (model.Enabled == false) continue;
if (model.DeviceNo == DeviceNo && model.Port != Port) return model;
ListUserSocket.CheckIn(model);
}
return null;
}
#endregion
#region 消除已回复消息
public int EndWaitMsg(ServerConnection model, string SequenceID)
{
SocketMessage msg = model.EndWaitMsg(SequenceID);
if (msg == null) return 0;
return msg.MessageID;
}
#endregion
}
#endregion
#region 客户端Socket
public class ClientSocket
{
public string IpAddress { get; set; }
public int Port { get; set; }
public ServerConnection UseSocket { get; set; }
public int RefshSecond { get; set; }
/// <summary>
/// 最大消息等待回复数量
/// </summary>
public int MaxWaitMsgNumber { get; set; }
/// <summary>
/// 超出多少秒没有数据通讯后连接自动断开
/// </summary>
public int OutTime { get; set; }
public int BuffSize { get; set; }
public int MaxSendNumber { get; set; }
public bool IsLongConnect { get; set; }
public bool IsLogin { get; set; }
public event Action<ServerConnection, DataEventArgs> ReceiveData;
public event Action<ServerConnection> ConnectSocketComplete;
public event Action<ServerConnection> CloseSocketComplete;
public event Action<string> ConnectSocketError;
public event Action<ServerConnection> OutTimeHappen;
public event Action<SocketMessage> SendError;
private AutoResetEvent AutoReset = new AutoResetEvent(false);
private bool IsRun = false;
private DateTime PrevTime = DateTime.Now;
private int CloseReConnectTime = 0;
public ClientSocket()
{
IsLongConnect = true;
IsLogin = false;
RefshSecond = 30;
MaxWaitMsgNumber = 16;
MaxSendNumber = 0;
OutTime = 180;
BuffSize = 32 * 1024;
UseSocket = new ServerConnection();
UseSocket.DataReceived += DataReceived;
UseSocket.CloseSocketed += Disconnected;
}
#region 开始监控
public void Start()
{
IsRun = true;
Thread t1 = new Thread(new ThreadStart(this.WhileListUserSocket));
t1.Name = "ClientSocket";
t1.Start();
}
#endregion
#region 停止
public void Stop()
{
IsRun = false;
AutoReset.Set();
CloseSocket(UseSocket);
}
#endregion
#region 连接
bool SocketAccept()
{
IPAddress broadcast = IPAddress.Parse(IpAddress);
IPEndPoint ep = new IPEndPoint(broadcast, Port);
Socket e = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
e.LingerState = new LingerOption(true, 0);
e.SendTimeout = 60000;
try
{
e.Connect(ep);
System.Threading.Thread.Sleep(1000);
UseSocket.PrevTime = DateTime.Now;
}
catch (Exception ex)
{
CloseReConnectTime = 60;
ErrorFollow.TraceWrite("连接失败", this.IpAddress+""+Port, ex.Message);
if (this.ConnectSocketError != null) this.ConnectSocketError(this.IpAddress);
return false;
}
SocketAsyncEventArgs args = new SocketAsyncEventArgs();
byte[] bytes = new byte[this.BuffSize];
args.SetBuffer(bytes, 0, this.BuffSize);
UseSocket.Start(e, args);
if (this.ConnectSocketComplete != null) this.ConnectSocketComplete(this.UseSocket);
return true;
}
#endregion
#region 读取消息
void DataReceived(ServerConnection sender, DataEventArgs e)
{
if (e.Data.Length == 0) return;
UseSocket.PrevTime = DateTime.Now;
if (this.ReceiveData != null) this.ReceiveData(sender, e);
}
#endregion
#region 对方关闭连接
void Disconnected(ServerConnection sender, SocketAsyncEventArgs e)
{
CloseReConnectTime = 60;
if (this.CloseSocketComplete != null) this.CloseSocketComplete(sender);
e.Dispose();
e = null;
//ErrorFollow.TraceWrite("TcpSocker.Disconnected", "", "对方关闭连接");
//CloseSocket(sender);
}
#endregion
#region 轮循消息列表
void WhileListUserSocket()
{
bool bk = false;
//SocketAccept();
while (IsRun)
{
try
{
if (UseSocket.Enabled == false)
{
if (this.IsLongConnect == true || UseSocket.ListMessage.Count > 0)
{
if (CloseReConnectTime > 0)
{
CloseReConnectTime = 0;
AutoReset.WaitOne(60000);
}
bk = SocketAccept();
if (bk == true) continue;
if (IsRun == true) AutoReset.WaitOne(60000);
}
else
{
if (IsRun == true) AutoReset.WaitOne(2000, false);
}
continue;
}
if (UseSocket.PrevTime.AddSeconds(this.OutTime) < DateTime.Now)
{
if (this.IsLongConnect == false)
{
CloseSocket(UseSocket);
bk = true;
continue;
}
else
{
//如果是长连接引发,心跳事件
if (this.OutTimeHappen != null)
{
this.OutTimeHappen(UseSocket);
UseSocket.PrevTime = DateTime.Now;
continue;
}
}
}
if (UseSocket.ListMessage.Count > 0)
{
//ErrorFollow.TraceWrite("发送数据", "", "数量:" + UseSocket.ListMessage.Count + ",等待数:" + UseSocket.WaitMsgNumber);
while (true)
{
SocketMessage Msg = UseSocket.GetNextSocketMessage(this.RefshSecond);
if (Msg == null) break;
if (UseSocket.WaitMsgNumber >= this.MaxWaitMsgNumber) break;
if (this.MaxSendNumber > 0 && Msg.SendNumber > this.MaxSendNumber)
{
UseSocket.EndWaitMsg(Msg.SequenceID);
continue;
}
if (this.Send(UseSocket, Msg) == false)
{
if (this.SendError != null) this.SendError(Msg);
break;
}
UseSocket.IncrementWaitMsgNumber();
AutoReset.WaitOne(10, false);
}
}
if (IsRun == true) AutoReset.WaitOne(1000, false);
}
catch (Exception ex)
{
CloseSocket(UseSocket);
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
}
#endregion
#region 发送数据
public bool Send(ServerConnection model, SocketMessage msg)
{
model.PrevTime = DateTime.Now;
try
{
msg.SendNumber++;
msg.SendTime = DateTime.Now;
if (msg.SendNumber > 1)
{
string m = "第" + msg.SendNumber + "次";
m += ",上次发送时间:" + msg.SendTime;
m += ",id:" + msg.MessageID;
m += ",流水号:" + msg.SequenceID;
m += ",FunNo:" + msg.FunNo;
m += ",DeviceNo:" + msg.DeviceNo;
ErrorFollow.TraceWrite("重发数据", "", m);
}
bool bk = model.SendData(msg.Bytes, 0, msg.Bytes.Length);
if (bk == false)
{
ErrorFollow.TraceWrite("发送数据失败", "", "断开连接");
CloseSocket(model);
}
return bk;
}
catch
{
ErrorFollow.TraceWrite("发送数据失败", "", "断开连接");
CloseSocket(model);
return false;
}
}
#endregion
#region 关闭连接
public void CloseSocket()
{
CloseSocket(this.UseSocket);
}
#endregion
#region 关闭连接
public void CloseSocket(ServerConnection model)
{
if (model.Enabled == false) return;
try
{
model.Disconnect();
}
catch
{ }
}
#endregion
#region 消除已回复消息
public int EndWaitMsg(string SequenceID)
{
try
{
SocketMessage msg = UseSocket.EndWaitMsg(SequenceID);
if (UseSocket.WaitMsgNumber == this.MaxSendNumber-1) UseSocket.WaitMsgNumber = 0;
if (msg == null) return 0;
return msg.MessageID;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("ClientSocket.EndWaitMsg", "", ex.Message);
}
return 0;
}
#endregion
}
#endregion
#region 文件下载服务器
public class FileService
{
private int Port = 11111;
public AutoResetEvent AutoReset = new AutoResetEvent(false);
public char SpaceChar = '^';
public static string WebPath = "";
SocketService ser = new SocketService();
public event Action<ServerConnection, Dictionary<string, string>> ReceiveData;
public event Action<ServerConnection> ConnectSocketComplete;
public event Action<ServerConnection> CloseSocketComplete;
public System.Security.Cryptography.MD5CryptoServiceProvider oMD5Hasher = new System.Security.Cryptography.MD5CryptoServiceProvider();
public FileService()
{
//ser.
ser.IsLongConnect = false;
ser.OutMaxSendNumberCloseConnect = true;
ser.MaxWaitMsgNumber = 16;
ser.MaxSendNumber = 2;
ser.OutTime = 60*3;
ser.RefshSecond = 10;
ser.ReceiveData += ser_ReceiveData;
ser.ConnectSocketComplete += ser_ConnectSocketComplete;
ser.CloseSocketComplete += ser_CloseSocketComplete;
}
#region 连接
void ser_ConnectSocketComplete(ServerConnection model)
{
if (this.ConnectSocketComplete != null) this.ConnectSocketComplete(model);
}
#endregion
#region 关闭连接
void ser_CloseSocketComplete(ServerConnection model)
{
if (model.fs != null)
{
model.fs.Close();
model.fs = null;
}
if (this.CloseSocketComplete != null) this.CloseSocketComplete(model);
}
#endregion
#region 启动监控
public void Start(int Port)
{
this.Port = Port;
if (this.Port == 0) return;
ser.BufferSize = 2 * 1024;
ser.Port = Port;
ser.Start();
}
#endregion
#region 停止监控
public void Stop()
{
if (this.Port == 0) return;
ser.Stop(null);
}
#endregion
#region 服务器读取到数据时发生
private void ser_ReceiveData(ServerConnection model, DataEventArgs arg2)
{
try
{
string Data = System.Text.Encoding.GetEncoding("GB2312").GetString(model.Data).Trim('\0');
ErrorFollow.TraceWrite("读取到数据", model.IpAddress, Data);
Dictionary<string, string> ReceiveModel = this.ParseData(Data);
string FunNo = ReceiveModel["TRANS_NO"];
switch (FunNo)
{
case "9999": //文件下载请求
DownFile(model, ReceiveModel);
break;
default:
if (this.ReceiveData != null) this.ReceiveData(model, ReceiveModel);
break;
}
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
#endregion
#region 解析返回数据
Dictionary<string, string> ParseData(string Data)
{
if (string.IsNullOrEmpty(Data) == true) return null;
//if (ErrorFollow.IsDebug == true) ErrorFollow.TraceWrite("解析返回数据", "", Data);
Dictionary<string, string> list = new Dictionary<string, string>();
string[] ss = Data.Split(this.SpaceChar);
foreach (string item in ss)
{
if (string.IsNullOrEmpty(item) == true) continue;
string[] sss = item.Split('=');
if (sss.Length == 1)
{
list.Add(sss[0].ToUpper(), "");
}
if (sss.Length == 2)
{
list.Add(sss[0].ToUpper(), sss[1]);
}
}
return list;
}
#endregion
#region 下载文件
public void DownFile(ServerConnection model, Dictionary<string, string> ReceiveModel)
{
NetworkStream ns = null;
Socket socker = null;
try
{
string FilePath = CustomIO.GetKeyValues(ReceiveModel, "FilePath");
if (FilePath.Contains(":") == false) FilePath = FileService.WebPath + FilePath;
bool IsExistsFile = File.Exists(FilePath);
socker = model.GetSocket();
ns = new NetworkStream(socker);
if (IsExistsFile == false)
{
ErrorFollow.TraceWrite("下载文件失败,文件不存在", model.IpAddress, FilePath);
byte[] fileBuffer = new byte[24];
for (int i = 8; i < 24; i++)
{
fileBuffer[i] = 255;
}
ns.Write(fileBuffer, 0, 24);
}
else
{
//传送头信息:文件长度,MD5校验码
model.fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read, FileShare.Read);
byte[] HeaderLen = BitConverter.GetBytes(model.fs.Length);
byte[] HeaderHash = oMD5Hasher.ComputeHash(model.fs);
ns.Write(HeaderLen, 0, HeaderLen.Length);
ns.Write(HeaderHash, 0, HeaderHash.Length);
byte[] fileBuffer = new byte[1024 * 4]; // 每次传1KB
int bytesRead;
int totalBytes = 0;
// 将文件流转写入网络流
int index = 0;
model.fs.Position = 0;
do
{
bytesRead = model.fs.Read(fileBuffer, 0, fileBuffer.Length);
if (bytesRead == 0) break;
ns.Write(fileBuffer, 0, bytesRead);
totalBytes += bytesRead; // 发送了的字节数
index++;
if (index == 10)
{
AutoReset.WaitOne(10, false);
index = 0;
model.PrevTime = DateTime.Now;
}
} while (bytesRead > 0);
model.fs.Close();
model.fs = null;
}
}
catch (Exception ex)
{
if (model.fs != null)
{
model.fs.Close();
model.fs = null;
}
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
#endregion
}
#endregion
#region 文件下载客户端
public class FileClient
{
public static string IpAddress = "";
public static int Port = 11111;
public static string SpaceChar = "^";
public int CilentID = 0;
public int DownFileID = 0;
public List<NetDownFile> FileManage = null;
public int ModelType = 0;
public bool IsSaveList = true;
public bool IsErrorStopDown = false;
public float Version = 0;
public object CustomModel = null;
private AutoResetEvent AutoReset = new AutoResetEvent(false);
public bool IsRun = true;
public string tempFilePath = "";
public string RunTime = "";
public event Action<FileClient> DownFileComplete; //下载文件完成
public event Action<FileClient> DownFileErrorComplete; //下载文件错误时发生
public event Action<NetDownFile> DownNoFileComplete; //服务器不存在这个文件
#region 启动监控
public void Start()
{
IsRun = true;
Thread t = new Thread(this.OnStart);
t.Start();
}
#endregion
#region 启动监控
public void Start(int ModelType, List<NetDownFile> ListModel)
{
this.ModelType = ModelType;
this.FileManage = ListModel;
IsRun = true;
string dir = SystemInfo.AppPath() + "TempFileDown";
if (Directory.Exists(dir) == false) Directory.CreateDirectory(dir);
tempFilePath = dir + "/" + DateTime.Now.ToString("MMddHHmmssfff") + ".txt";
Thread t = new Thread(this.OnStart);
t.Start();
}
#endregion
#region 启动监控
public void Start(int ModelType, string filePath, List<NetDownFile> ListModel)
{
this.ModelType = ModelType;
this.FileManage = ListModel;
IsRun = true;
string dir = SystemInfo.AppPath() + "TempFileDown";
if (Directory.Exists(dir) == false) Directory.CreateDirectory(dir);
tempFilePath = filePath;
Thread t = new Thread(this.OnStart);
t.Start();
}
#endregion
#region 停止监控
public void Stop()
{
FileManage.Clear();
IsRun = false;
AutoReset.Set();
}
#endregion
#region 保存下载文件列表
public void SaveFileList()
{
try
{
if (this.IsSaveList == false) return;
if (string.IsNullOrEmpty(tempFilePath) == true)
{
string dir = SystemInfo.AppPath() + "TempFileDown";
if (Directory.Exists(dir) == false) Directory.CreateDirectory(dir);
tempFilePath = dir + "/" + DateTime.Now.ToString("MMddHHmmssfff") + ".txt";
}
StringBuilder sb = new StringBuilder();
sb.Append("DownFileID=" + this.DownFileID + FileClient.SpaceChar);
sb.Append("ModelType=" + this.ModelType + FileClient.SpaceChar);
sb.Append("RowCount=" + FileManage.Count + FileClient.SpaceChar);
sb.Append("IsErrorStopDown=" + IsErrorStopDown.ToString() + FileClient.SpaceChar);
int index = 1;
foreach (NetDownFile item in FileManage)
{
sb.Append("DownFileName[" + index + "]=" + item.DownFileName + FileClient.SpaceChar);
sb.Append("DownID[" + index + "]=" + item.DownID + FileClient.SpaceChar);
sb.Append("SaveFileName[" + index + "]=" + item.SaveFileName + FileClient.SpaceChar);
sb.Append("IsDownComplete[" + index + "]=" + item.IsDownComplete.ToString() + FileClient.SpaceChar);
sb.Append("FileType[" + index + "]=" + item.FileType + FileClient.SpaceChar);
index++;
}
using (StreamWriter sw = new StreamWriter(tempFilePath, false, System.Text.Encoding.GetEncoding("GB2312")))
{
sw.WriteLine(sb.ToString());
sw.Close();
}
}
catch (Exception ex)
{
ErrorFollow.TraceWrite("保存下载文件列表", ex.StackTrace, ex.Message);
}
}
#endregion
#region 文件下载
void OnStart()
{
DateTime StartTime = DateTime.Now;
SaveFileList();
FileStream fs = null;
NetworkStream ns = null;
TcpClient tcp = null;
try
{
System.Security.Cryptography.MD5CryptoServiceProvider oMD5Hasher = new System.Security.Cryptography.MD5CryptoServiceProvider();
bool bk = false;
#region 循环
foreach (NetDownFile item in FileManage)
{
if (item.IsDownComplete == true) continue;
try
{
if (File.Exists(item.SaveFileName) == true) File.Delete(item.SaveFileName);
}
catch
{
ErrorFollow.TraceWrite("下载文件", "", item.SaveFileName + "文件删除失败");
bk = true;
break;
}
string dir = Path.GetDirectoryName(item.SaveFileName);
if (Directory.Exists(dir) == false) Directory.CreateDirectory(dir);
string path = item.SaveFileName + ".temp";
if (File.Exists(path) == true)
{
DateTime dt = DateTime.Now;
FileInfo finfo = new FileInfo(path);
if (dt.AddMinutes(-1) < finfo.LastWriteTime)
{
finfo = null;
ErrorFollow.TraceWrite("下载文件", "", path + "文件已经在下载");
bk = true;
break;
}
File.Delete(path);
}
IPAddress broadcast = IPAddress.Parse(IpAddress);
IPEndPoint ep = new IPEndPoint(broadcast, Port);
tcp = new TcpClient();
tcp.Connect(ep);
ns = tcp.GetStream();
//这里发送文件下载请求
StringBuilder sb = new StringBuilder();
if (item.FileType == 0)
{
sb.Append("TRANS_NO=9998" + FileClient.SpaceChar);
}
else
{
sb.Append("TRANS_NO=9999" + FileClient.SpaceChar);
}
sb.Append("FilePath=" + item.DownFileName + FileClient.SpaceChar);
byte[] bytes = System.Text.Encoding.GetEncoding("GB2312").GetBytes(sb.ToString());
ns.Write(bytes, 0, bytes.Length);
//AutoReset.WaitOne(1000, false);
byte[] fileHeader = new byte[24];
byte[] fileBuffer = new byte[1024 * 4]; // 每次收1KB
if (File.Exists(path)) File.Delete(path);
fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite);
// 从缓存buffer中读入到文件流中
int bytesRead;
int totalBytes = 0;
int index = 0;
byte[] HeaderHash = null;
string CheckOutCode = "";
do
{
bytesRead = ns.Read(fileBuffer, 0, fileBuffer.Length);
if (totalBytes < 24)
{
int count = 24 - totalBytes;
if (bytesRead < count) count = bytesRead;
Buffer.BlockCopy(fileBuffer, 0, fileHeader, totalBytes, count);
if (totalBytes + count >= 24)
{
item.Length = BitConverter.ToInt64(fileHeader, 0);
if (item.Length == 0) break;
item.CheckOutCode = BitConverter.ToString(fileHeader, 8, 16);
if (bytesRead > 24) fs.Write(fileBuffer, count, bytesRead - count);
}
}
else
{
fs.Write(fileBuffer, 0, bytesRead);
}
totalBytes += bytesRead;
if (item.Length > 0 && totalBytes >= item.Length + 24) break;
if (index == 10) { AutoReset.WaitOne(10, false); if (IsRun == false) return; index = 0; }
} while (bytesRead > 0);
if (fs.Length > 0)
{
fs.Position = 0;
HeaderHash = oMD5Hasher.ComputeHash(fs);
CheckOutCode = BitConverter.ToString(HeaderHash, 0, 16);
}
long FileLength = fs.Length;
fs.Close();
fs = null;
ns.Close();
ns = null;
tcp.Close();
tcp = null;
bool bkk = true;
if (item.Length == 0 && fileHeader.Length == 24)
{
bkk = false;
for (int i = 8; i < 24; i++)
{
if (fileHeader[i] != 255) { bkk = true; break; }
}
}
if (bkk==false)
{
ErrorFollow.TraceWrite("下载文件", "", "服务器不存在这个文件:" + item.DownFileName);
item.IsDownComplete = true;
if (this.DownNoFileComplete != null) this.DownNoFileComplete(item);
File.Delete(path);
bk = false;
break;
}
else if (item.Length == 0 || HeaderHash == null)
{
ErrorFollow.TraceWrite("下载文件出错", "文件长度不能等于0", item.DownFileName);
File.Delete(path);
bk = true;
break;
}
else if (FileLength != item.Length)
{
ErrorFollow.TraceWrite("下载文件出错", "文件长度错误", item.DownFileName);
File.Delete(path);
bk = true;
break;
}
else if (CheckOutCode != item.CheckOutCode)
{
ErrorFollow.TraceWrite("下载文件出错", "MD5校验失败", item.DownFileName);
File.Delete(path);
bk = true;
break;
}
else
{
ErrorFollow.TraceWrite("下载文件成功", "", item.DownFileName);
item.IsDownComplete = true;
File.Move(path, item.SaveFileName);
}
}
#endregion
if (bk == false)
{
DateTime StopTime = DateTime.Now;
TimeSpan ts = StopTime - StartTime;
RunTime = ts.ToString();
IsRun = false;
if (this.IsSaveList == true) File.Delete(tempFilePath);
if (this.DownFileComplete != null) this.DownFileComplete(this);
}
else
{
if (this.IsErrorStopDown == true)
{
ErrorFollow.TraceWrite("下载文件错误", "", "停止下载");
if (this.DownFileErrorComplete != null) this.DownFileErrorComplete(this);
}
else
{
ErrorFollow.TraceWrite("下载文件出错", "", "60秒后重新下载");
AutoReset.WaitOne(60000, false);
if (IsRun == false) return;
OnStart();
return;
}
}
}
catch (Exception ex)
{
try
{
if (fs != null)
{
fs.Close();
fs = null;
}
if (ns != null)
{
ns.Close();
ns = null;
}
if (tcp != null)
{
tcp.Close();
tcp = null;
}
}
catch
{ }
if (this.IsErrorStopDown == true)
{
ErrorFollow.TraceWrite("下载文件出错", ex.StackTrace, ex.Message);
if (this.DownFileErrorComplete != null) this.DownFileErrorComplete(this);
}
else
{
ErrorFollow.TraceWrite("下载文件出错,60秒后重新下载", ex.StackTrace, ex.Message);
AutoReset.WaitOne(60000, false);
if (IsRun == false) return;
OnStart();
}
}
}
#endregion
}
#endregion
#region 文件下载信息
public class NetDownFile
{
public int DownID = 0;
public string SaveFileName = "";
public string DownFileName = "";
public long Length = 0;
public string CheckOutCode = "";
public bool IsDownComplete = false;
public int FileType = 1; //0医生照片下载1文件下载
public void CreateFile()
{
if (File.Exists(SaveFileName) == true) File.Delete(SaveFileName);
}
public NetDownFile Copy()
{
NetDownFile model = new NetDownFile();
model.DownID = this.DownID;
model.SaveFileName = this.SaveFileName;
model.DownFileName = this.DownFileName;
model.Length = this.Length;
model.CheckOutCode = this.CheckOutCode;
model.IsDownComplete = this.IsDownComplete;
model.FileType = this.FileType;
return model;
}
}
#endregion
}