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.

493 lines
16 KiB
C#

using System;
using System.Net.Sockets;
using System.Net;
using System.Collections.Generic;
using System.Collections;
using System.Threading;
using HuizhongLibrary.Log;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
namespace HuizhongLibrary.Network
{
/// <summary>
/// Represents a callback used to inform a listener that a ServerConnection has received data.
/// </summary>
/// <param name="sender">The sender of the callback.</param>
/// <param name="e">The DataEventArgs object containging the received data.</param>
public delegate void DataReceivedCallback(ServerConnection sender, DataEventArgs e);
/// <summary>
/// Represents a callback used to inform a listener that a ServerConnection has disconnected.
/// </summary>
/// <param name="sender">The sender of the callback.</param>
/// <param name="e">The SocketAsyncEventArgs object used by the ServerConnection.</param>
public delegate void DisconnectedCallback(ServerConnection sender, SocketAsyncEventArgs e);
/// <summary>
/// A connection to our server.
/// </summary>
public class ServerConnection
{
public string IpAddress { get; set; }
public int Port { get; set; }
public string DeviceNo { get; set; }
public DateTime PrevTime { get; set; }
public List<byte> SocketBuffer { get; set; }
public SocketMessages ListMessage { get; set; }
public bool Enabled { get; set; }
public bool IsLogin { get; set; }
public string ConnectIp { get; set; }
public int ConnectPort { get; set; }
public int FileLength { get; set; }
public int ReceiveLen { get; set; }
public Byte[] Data { get; set; }
public string BuffData { get; set; }
public int RefshSecond { get; set; }
public bool IsSyncSend { get; set; }
public int CheckConnectNumber { get; set; } //连接状态验证次数
public int WaitMsgNumber = 0;
public bool IsWebSocket = false; //WebSocket握手协议是否完成
public FileStream fs = null;
private int MaxSendNumber = 0;
private int MaxWaitMsgNumber = 0;
private DateTime CacheDataTime = DateTime.Now;
public SocketAsyncEventArgs eventArgs;
public Socket socket;
public event Action<ServerConnection> SendCompleted;
public event Action<ServerConnection, DataEventArgs> DataReceived;
public event Action<ServerConnection, SocketAsyncEventArgs> CloseSocketed;
#region 初始化
public ServerConnection()
{
CheckConnectNumber = 3;
FileLength = 0;
IsLogin = false;
PrevTime = DateTime.Now;
WaitMsgNumber = 0;
SocketBuffer = new List<byte>();
ListMessage = new SocketMessages();
//Data = new byte[2048];
}
public ServerConnection(Socket socket, SocketAsyncEventArgs args)
{
//Data = new byte[2048];
FileLength = 0;
IsLogin = false;
PrevTime = DateTime.Now;
WaitMsgNumber = 0;
SocketBuffer = new List<byte>();
ListMessage = new SocketMessages();
if (socket.AddressFamily == AddressFamily.InterNetwork || socket.AddressFamily == AddressFamily.Unspecified)
{
string[] RemoteEndPoint = socket.RemoteEndPoint.ToString().Split(':');
this.IpAddress = RemoteEndPoint[0];
this.Port = Convert.ToInt32(RemoteEndPoint[1]);
ErrorFollow.TraceWrite("请求连接", "", IpAddress);
//this.DeviceNo = this.IpAddress.Split(Convert.ToChar("."))[3];
}
else
{
this.IpAddress = "";
}
this.Enabled = true;
this.socket = socket;
eventArgs = args;
eventArgs.Completed += ReceivedCompleted;
ListenForData(eventArgs);
}
#endregion
#region 连接
public void Start(Socket socket, SocketAsyncEventArgs args)
{
if (socket.AddressFamily == AddressFamily.InterNetwork || socket.AddressFamily == AddressFamily.Unspecified)
{
string[] RemoteEndPoint = socket.RemoteEndPoint.ToString().Split(':');
this.IpAddress = RemoteEndPoint[0];
this.Port = Convert.ToInt32(RemoteEndPoint[1]);
}
else
{
this.IpAddress = "";
}
this.Enabled = true;
if (this.socket != null) this.socket = null;
if (this.eventArgs != null)
{
eventArgs.Dispose();
eventArgs = null;
}
this.socket = socket;
eventArgs = args;
eventArgs.Completed += ReceivedCompleted;
ListenForData(eventArgs);
}
#endregion
#region 返回要发送的消息
public SocketMessage GetNextSocketMessage(int RefshSecond)
{
var item=ListMessage.GetNextSocketMessage(RefshSecond);
if (item == null) return null;
if (item.SendNumber > 0)
{
ErrorFollow.TraceWrite("重发", "", item.FunNo);
DecrementWaitMsgNumber();
}
return item;
}
#endregion
#region 移除已发送消息
public void RemoveSocketMessage()
{
ListMessage.RemoveEmploy();
}
#endregion
#region 增加等待回复的消息数
public void IncrementWaitMsgNumber()
{
Interlocked.Increment(ref WaitMsgNumber);
}
#endregion
#region 减少等待回复的消息数
public void DecrementWaitMsgNumber()
{
Interlocked.Decrement(ref WaitMsgNumber);
//Interlocked.Exchange<string>(ref 变量,11);
}
#endregion、
#region 消除已回复消息
public SocketMessage EndWaitMsg(string SequenceID)
{
try
{
DecrementWaitMsgNumber();
SocketMessage msg = ListMessage.CheckOut(SequenceID);
return msg;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
return null;
}
#endregion
#region 消除已回复消息
public SocketMessage EndFirstWaitMsg()
{
try
{
DecrementWaitMsgNumber();
SocketMessage msg = ListMessage.CheckOut();
return msg;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
return null;
}
#endregion
#region 返回消息
public SocketMessage GetSocketMessage(string SequenceID)
{
return ListMessage.GetSocketMessage(SequenceID);
}
#endregion
#region 合并缓存数据
public void AddData(byte[] RevData, int Offset, int Len)
{
try
{
if (CacheDataTime.AddSeconds(15) < DateTime.Now)
{
SocketBuffer.Clear();
}
this.ReceiveLen = Len + SocketBuffer.Count;
if (Data.Length < this.ReceiveLen) Data = new byte[ReceiveLen];
for (int i = 0; i < SocketBuffer.Count; i++)
{
Data[i] = SocketBuffer[i];
}
Buffer.BlockCopy(RevData, Offset, Data, SocketBuffer.Count, Len);
SocketBuffer.Clear();
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
#endregion
#region 新增缓存
public void AddBuff(byte[] SrcArray, int offset)
{
try
{
for (int i = offset; i < ReceiveLen; i++)
{
SocketBuffer.Add(SrcArray[i]);
}
CacheDataTime = DateTime.Now;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
}
#endregion
#region 清理内存
public void Dispose()
{
if (SocketBuffer != null) SocketBuffer.Clear();
SocketBuffer = null;
if (ListMessage!=null) ListMessage.Clear();
ListMessage = null;
}
#endregion
#region 打包服务器数据
/// <summary>
/// 打包服务器数据
/// </summary>
/// <param name="message">数据</param>
/// <returns>数据包</returns>
public static byte[] PackData(string message)
{
byte[] contentBytes = null;
byte[] temp = Encoding.UTF8.GetBytes(message);
if (temp.Length < 126)
{
contentBytes = new byte[temp.Length + 2];
contentBytes[0] = 0x81;
contentBytes[1] = (byte)temp.Length;
Array.Copy(temp, 0, contentBytes, 2, temp.Length);
}
else if (temp.Length < 0xFFFF)
{
contentBytes = new byte[temp.Length + 4];
contentBytes[0] = 0x81;
contentBytes[1] = 126;
contentBytes[2] = (byte)(temp.Length >> 8 & 0xFF);
contentBytes[3] = (byte)(temp.Length & 0xFF);
Array.Copy(temp, 0, contentBytes, 4, temp.Length);
}
else
{
// 暂不处理超长内容
}
return contentBytes;
}
#endregion
#region Public Methods
/// <summary>
/// Disconnects the client.
/// </summary>
public void Disconnect()
{
lock (this)
{
CloseConnection(eventArgs);
}
}
/// <summary>
/// Sends data to the client.
/// </summary>
/// <param name="data">The data to send.</param>
/// <param name="offset">The offset into the data.</param>
/// <param name="count">The ammount of data to send.</param>
public bool SendData(Byte[] data, Int32 offset, Int32 count)
{
try
{
lock (this)
{
if (socket.Connected == false) return false;
//bool bk=socket.Poll(-1, SelectMode.SelectWrite);
this.PrevTime = DateTime.Now;
int i = socket.Send(data, offset, count, SocketFlags.None);
if (i <= 0) return false;
}
}
catch (Exception ex)
{
return false;
}
return true;
}
#region WebSocket专用
public bool SendData(string data)
{
lock (this)
{
if (socket.Connected == false) return false;
//bool bk=socket.Poll(-1, SelectMode.SelectWrite);
this.PrevTime = DateTime.Now;
byte[] bytes = PackData(data);
int i = socket.Send(bytes, 0, bytes.Length, SocketFlags.None);
if (i <= 0) return false;
}
return true;
}
#endregion
#endregion
#region 获取Socket
public Socket GetSocket()
{
lock (this)
{
return socket;
}
}
#endregion
#region Private Methods
/// <summary>
/// Starts and asynchronous recieve.
/// </summary>
/// <param name="args">The SocketAsyncEventArgs to use.</param>
private void ListenForData(SocketAsyncEventArgs args)
{
lock (this)
{
if (socket == null) return;
if (socket.Connected)
{
socket.InvokeAsyncMethod(socket.ReceiveAsync,
ReceivedCompleted, args);
}
}
}
/// <summary>
/// Called when an asynchronous receive has completed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="args">The SocketAsyncEventArgs for the operation.</param>
private void ReceivedCompleted(Object sender, SocketAsyncEventArgs args)
{
try
{
if (args.BytesTransferred == 0)
{
if (string.IsNullOrEmpty(this.DeviceNo)==false)Disconnect();
return;
}
if (args.SocketError != SocketError.Success)
{
if (string.IsNullOrEmpty(this.DeviceNo) == false) Disconnect();
return;
}
this.Data = new byte[args.BytesTransferred];
this.ReceiveLen = this.Data.Length;
Buffer.BlockCopy(args.Buffer, args.Offset, this.Data, args.Offset, args.BytesTransferred);
if (this.DataReceived!=null)this.DataReceived(this, new DataEventArgs() { Data = this.Data, Length = this.ReceiveLen });
ListenForData(args);
//if (state.socket.Available == 0)
//{
// ListenForData(args);
//}
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
Disconnect();
}
}
#region 输出数据日志
string WaitData(byte[] bytes, int index, int Length)
{
try
{
return Encoding.UTF8.GetString(bytes, index, Length);
}
catch
{
string a = "";
foreach (var item in bytes)
{
a += item.ToString("X");
}
return a;
}
}
#endregion
/// <summary>
/// Closes the connection.
/// </summary>
/// <param name="args">The SocketAsyncEventArgs for the connection.</param>
private void CloseConnection(SocketAsyncEventArgs args)
{
if (this.Enabled == false)return;
this.Enabled = false;
this.WaitMsgNumber = 0;
if (socket == null) return;
try
{
socket.Shutdown(SocketShutdown.Both);
}
catch
{ }
try
{
socket.Close();
}
catch
{ }
try
{
Dispose();
args.Completed -= ReceivedCompleted; //MUST Remember This!
socket = null;
this.Data = null;
}
catch (Exception ex)
{
ErrorFollow.TraceWrite(ex.TargetSite.Name, ex.StackTrace, ex.Message);
}
if (this.CloseSocketed != null) this.CloseSocketed(this, args);
}
#endregion
#region Events
/// <summary>
/// Fires the DataReceivedCallback.
/// </summary>
/// <param name="data">The data which was received.</param>
/// <param name="remoteEndPoint">The address the data came from.</param>
/// <param name="callback">The callback.</param>
private void OnDataReceived(DataReceivedCallback callback)
{
callback(this, new DataEventArgs() { Data = this.Data, Length = this.ReceiveLen });
}
/// <summary>
/// Fires the DisconnectedCallback.
/// </summary>
/// <param name="args">The SocketAsyncEventArgs for this connection.</param>
/// <param name="callback">The callback.</param>
private void OnDisconnected(SocketAsyncEventArgs args, DisconnectedCallback callback)
{
callback(this, args);
}
#endregion
}
}