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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}