using System;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Lskj.SocketService
{
///
/// 服务入口,建立Socket监听,负责接收连接,绑定连接对象,处理异步事件返回的接收和发送事件
///
public class AsyncSocketServer
{
private Socket _listenSocket;
///
/// 最大支持连接个数
///
private int _numConnections;
///
/// 每个连接接收缓存大小
///
private int _receiveBufferSize;
///
/// 限制访问接收连接的线程数,用来控制最大并发数
///
private Semaphore _maxNumberAcceptedClients;
///
/// Socket最大超时时间,单位为MS
///
private int _socketTimeOutMS;
public int SocketTimeOutMS { get { return _socketTimeOutMS; } set { _socketTimeOutMS = value; } }
private AsyncSocketUserTokenPool _asyncSocketUserTokenPool;
private AsyncSocketUserTokenList _asyncSocketUserTokenList;
private LogOutputSocketProtocolMgr _logOutputSocketProtocolMgr;
private UploadSocketProtocolMgr _uploadSocketProtocolMgr;
private DownloadSocketProtocolMgr _downloadSocketProtocolMgr;
///
/// 守护进程,用于关闭超时连接
///
private DaemonThread _daemonThread;
///
/// 管理所有正在执行的AsyncSocketUserToken,是一个列表
///
/// The asynchronous socket user token list.
public AsyncSocketUserTokenList AsyncSocketUserTokenList
{
get { return _asyncSocketUserTokenList; }
}
///
/// LogOutputSocketProtocol的管理对象
///
/// The log output socket protocol MGR.
public LogOutputSocketProtocolMgr LogOutputSocketProtocolMgr
{
get { return _logOutputSocketProtocolMgr; }
}
///
/// UploadSocketProtocol的管理对象,用于检测是否同时上传同一个文件
///
/// The upload socket protocol MGR.
public UploadSocketProtocolMgr UploadSocketProtocolMgr { get { return _uploadSocketProtocolMgr; } }
///
/// DownloadSocketProtocol的管理对象
///
/// The download socket protocol MGR.
public DownloadSocketProtocolMgr DownloadSocketProtocolMgr { get { return _downloadSocketProtocolMgr; } }
///
/// 说明:处理Socket客户端发送的请求
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The source of the event.
/// The instance containing the event data.
private void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs acceptEventArgs)
{
try
{
ProcessAccept(acceptEventArgs);
}
catch (Exception E)
{
Program.Logger.ErrorFormat("Accept client {0} error, message: {1}", acceptEventArgs.AcceptSocket, E.Message);
Program.Logger.Error(E.StackTrace);
}
}
///
/// 说明:完成异步操作的事件
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The source of the event.
/// The instance containing the event data.
/// The last operation completed on the socket was not a receive or send
private void IO_Completed(object sender, SocketAsyncEventArgs asyncEventArgs)
{
AsyncSocketUserToken userToken = asyncEventArgs.UserToken as AsyncSocketUserToken;
userToken.ActiveDateTime = DateTime.Now;
try
{
lock (userToken)
{
if (asyncEventArgs.LastOperation == SocketAsyncOperation.Receive)
ProcessReceive(asyncEventArgs);
else if (asyncEventArgs.LastOperation == SocketAsyncOperation.Send)
ProcessSend(asyncEventArgs);
else
throw new ArgumentException("The last operation completed on the socket was not a receive or send");
}
}
catch (Exception E)
{
Program.Logger.ErrorFormat("IO_Completed {0} error, message: {1}", userToken.ConnectSocket, E.Message);
Program.Logger.Error(E.StackTrace);
}
}
///
/// 说明:创建对应传输协议
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The user token.
private void BuildingSocketInvokeElement(AsyncSocketUserToken userToken)
{
byte flag = userToken.ReceiveEventArgs.Buffer[userToken.ReceiveEventArgs.Offset];
if (flag == (byte)ProtocolFlag.Upload)
userToken.AsyncSocketInvokeElement = new UploadSocketProtocol(this, userToken);
else if (flag == (byte)ProtocolFlag.Download)
userToken.AsyncSocketInvokeElement = new DownloadSocketProtocol(this, userToken);
else if (flag == (byte)ProtocolFlag.RemoteStream)
userToken.AsyncSocketInvokeElement = new RemoteStreamSocketProtocol(this, userToken);
else if (flag == (byte)ProtocolFlag.Throughput)
userToken.AsyncSocketInvokeElement = new ThroughputSocketProtocol(this, userToken);
else if (flag == (byte)ProtocolFlag.Control)
userToken.AsyncSocketInvokeElement = new ControlSocketProtocol(this, userToken);
else if (flag == (byte)ProtocolFlag.LogOutput)
userToken.AsyncSocketInvokeElement = new LogOutputSocketProtocol(this, userToken);
if (userToken.AsyncSocketInvokeElement != null)
{
Program.Logger.InfoFormat("Building socket invoke element {0}.Local Address: {1}, Remote Address: {2}",
userToken.AsyncSocketInvokeElement, userToken.ConnectSocket.LocalEndPoint, userToken.ConnectSocket.RemoteEndPoint);
}
}
///
/// 说明:处理接收请求
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The instance containing the event data.
private void ProcessAccept(SocketAsyncEventArgs acceptEventArgs)
{
Program.Logger.InfoFormat("Client connection accepted. Local Address: {0}, Remote Address: {1}",
acceptEventArgs.AcceptSocket.LocalEndPoint, acceptEventArgs.AcceptSocket.RemoteEndPoint);
AsyncSocketUserToken userToken = _asyncSocketUserTokenPool.Pop();
_asyncSocketUserTokenList.Add(userToken); // 添加到正在连接列表
userToken.ConnectSocket = acceptEventArgs.AcceptSocket;
userToken.ConnectDateTime = DateTime.Now;
try
{
bool willRaiseEvent = userToken.ConnectSocket.ReceiveAsync(userToken.ReceiveEventArgs); // 投递接收请求
if (!willRaiseEvent)
{
lock (userToken)
{
ProcessReceive(userToken.ReceiveEventArgs);
}
}
}
catch (Exception E)
{
Program.Logger.ErrorFormat("Accept client {0} error, message: {1}", userToken.ConnectSocket, E.Message);
Program.Logger.Error(E.StackTrace);
}
StartAccept(acceptEventArgs); //把当前异步事件释放,等待下次连接
}
///
/// 说明:处理接收的套接字
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The instance containing the event data.
private void ProcessReceive(SocketAsyncEventArgs receiveEventArgs)
{
AsyncSocketUserToken userToken = receiveEventArgs.UserToken as AsyncSocketUserToken;
if (userToken.ConnectSocket == null)
return;
userToken.ActiveDateTime = DateTime.Now;
if (userToken.ReceiveEventArgs.BytesTransferred > 0 && userToken.ReceiveEventArgs.SocketError == SocketError.Success)
{
int offset = userToken.ReceiveEventArgs.Offset;
int count = userToken.ReceiveEventArgs.BytesTransferred;
if ((userToken.AsyncSocketInvokeElement == null) & (userToken.ConnectSocket != null)) //存在Socket对象,并且没有绑定协议对象,则进行协议对象绑定
{
BuildingSocketInvokeElement(userToken);
offset = offset + 1;
count = count - 1;
}
if (userToken.AsyncSocketInvokeElement == null) //如果没有解析对象,提示非法连接并关闭连接
{
Program.Logger.WarnFormat("Illegal client connection. Local Address: {0}, Remote Address: {1}", userToken.ConnectSocket.LocalEndPoint,
userToken.ConnectSocket.RemoteEndPoint);
CloseClientSocket(userToken);
}
else
{
if (count > 0) //处理接收数据
{
if (!userToken.AsyncSocketInvokeElement.ProcessReceive(userToken.ReceiveEventArgs.Buffer, offset, count))
{ // 如果处理数据返回失败,则断开连接
CloseClientSocket(userToken);
}
else //否则投递下次介绍数据请求
{
bool willRaiseEvent = userToken.ConnectSocket.ReceiveAsync(userToken.ReceiveEventArgs); //投递接收请求
if (!willRaiseEvent)
ProcessReceive(userToken.ReceiveEventArgs);
}
}
else
{
bool willRaiseEvent = userToken.ConnectSocket.ReceiveAsync(userToken.ReceiveEventArgs); //投递接收请求
if (!willRaiseEvent)
ProcessReceive(userToken.ReceiveEventArgs);
}
}
}
else
{
CloseClientSocket(userToken);
}
}
///
/// 说明:发送指令
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The instance containing the event data.
/// true if XXXX, false otherwise.
private bool ProcessSend(SocketAsyncEventArgs sendEventArgs)
{
AsyncSocketUserToken userToken = sendEventArgs.UserToken as AsyncSocketUserToken;
if (userToken.AsyncSocketInvokeElement == null)
return false;
userToken.ActiveDateTime = DateTime.Now;
if (sendEventArgs.SocketError == SocketError.Success)
return userToken.AsyncSocketInvokeElement.SendCompleted(); //调用子类回调函数
else
{
CloseClientSocket(userToken);
return false;
}
}
public AsyncSocketServer(int numConnections)
{
_numConnections = numConnections;
_receiveBufferSize = ProtocolConst.ReceiveBufferSize;
_asyncSocketUserTokenPool = new AsyncSocketUserTokenPool(numConnections);
_asyncSocketUserTokenList = new AsyncSocketUserTokenList();
_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections);
_logOutputSocketProtocolMgr = new LogOutputSocketProtocolMgr();
_uploadSocketProtocolMgr = new UploadSocketProtocolMgr();
_downloadSocketProtocolMgr = new DownloadSocketProtocolMgr();
}
///
/// 说明:初始化
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
public void Init()
{
AsyncSocketUserToken userToken;
for (int i = 0; i < _numConnections; i++) // 按照连接数建立读写对象
{
userToken = new AsyncSocketUserToken(_receiveBufferSize);
userToken.ReceiveEventArgs.Completed += new EventHandler(IO_Completed);
userToken.SendEventArgs.Completed += new EventHandler(IO_Completed);
_asyncSocketUserTokenPool.Push(userToken);
}
}
///
/// 说明:启动Socket服务监听
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The local end point.
public void Start(IPEndPoint localEndPoint)
{
_listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
_listenSocket.Bind(localEndPoint);
_listenSocket.Listen(_numConnections);
Program.Logger.InfoFormat("Start listen socket {0} success", localEndPoint.ToString());
StartAccept(null);
_daemonThread = new DaemonThread(this);
}
///
/// 说明:释放异步事件
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The instance containing the event data.
public void StartAccept(SocketAsyncEventArgs acceptEventArgs)
{
if (acceptEventArgs == null)
{
acceptEventArgs = new SocketAsyncEventArgs();
acceptEventArgs.Completed += new EventHandler(AcceptEventArg_Completed);
}
else
{
acceptEventArgs.AcceptSocket = null; // 释放上次绑定的Socket,等待下一个Socket连接
}
_maxNumberAcceptedClients.WaitOne(); //获取信号量
bool willRaiseEvent = _listenSocket.AcceptAsync(acceptEventArgs);
if (!willRaiseEvent)
{
ProcessAccept(acceptEventArgs);
}
}
///
/// 说明:发送异步数据
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The connect socket.
/// The instance containing the event data.
/// The buffer.
/// The offset.
/// The count.
/// true if XXXX, false otherwise.
public bool SendAsyncEvent(Socket connectSocket, SocketAsyncEventArgs sendEventArgs, byte[] buffer, int offset, int count)
{
if (connectSocket == null)
return false;
sendEventArgs.SetBuffer(buffer, offset, count);
bool willRaiseEvent = connectSocket.SendAsync(sendEventArgs);
if (!willRaiseEvent)
{
return ProcessSend(sendEventArgs);
}
else
return true;
}
///
/// 说明:关闭指定的Socket连接
/// 创建人:龚宇超
/// 创建日期:2018-01-24
/// 修改人:
/// 修改日期:
/// 修改备注:
/// 版本:1.0
///
/// The user token.
public void CloseClientSocket(AsyncSocketUserToken userToken)
{
if (userToken.ConnectSocket == null)
return;
string socketInfo = string.Format("Local Address: {0} Remote Address: {1}", userToken.ConnectSocket.LocalEndPoint,
userToken.ConnectSocket.RemoteEndPoint);
Program.Logger.InfoFormat("Client connection disconnected. {0}", socketInfo);
try
{
userToken.ConnectSocket.Shutdown(SocketShutdown.Both);
}
catch (Exception E)
{
Program.Logger.ErrorFormat("CloseClientSocket Disconnect client {0} error, message: {1}", socketInfo, E.Message);
}
userToken.ConnectSocket.Close();
userToken.ConnectSocket = null; //释放引用,并清理缓存,包括释放协议对象等资源
_maxNumberAcceptedClients.Release();
_asyncSocketUserTokenPool.Push(userToken);
_asyncSocketUserTokenList.Remove(userToken);
}
}
}