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.

412 lines
13 KiB
C#

using System;
using System.Net.Sockets;
using System.Net;
using System.Collections.Generic;
using System.Collections;
using System.Threading;
using NetLibrary.Log;
using System.IO;
using System.Text;
namespace NetLibrary.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 int RefshSecond { get; set; }
public bool IsSyncSend { get; set; }
public int CheckConnectNumber { get; set; } //连接状态验证次数
public int WaitMsgNumber = 0;
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]);
}
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 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()
{
SocketBuffer = null;
ListMessage.Clear();
ListMessage = null;
}
#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)
{
lock (this)
{
if (socket.Connected == false) return false;
//bool bk=socket.Poll(-1, SelectMode.SelectWrite);
int i=socket.Send(data, offset, count, SocketFlags.None);
if (i <= 0) return false;
}
return true;
}
#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.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)
{
Disconnect();
return;
}
if (args.SocketError != SocketError.Success)
{
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
{
SocketBuffer.Clear();
ListMessage.Clear();
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
}
}