注:代码仅做演示,不能直接编译。 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Net.Sockets; using System.Threading; using System.Timers; using System.Net; using XXX.Platform.Common.Tools; namespace XXX.Platform.Common.Sockets { /// <summary> /// 封装IOCP的Socket对象 /// </summary> public class AsyncIocpSocket : AsyncSocketObject { /// <summary> /// buffer管理器 /// </summary> protected BufferManager bufferManager = new BufferManager(); /// <summary> /// SocketAsyncEventArgs对象池 /// </summary> protected ObjectPool<ReadWriteSocketAsyncEventArgsEx> socketReadWritePool; /// <summary> /// SocketAsyncEventArgs在线的列表 /// </summary> protected SyncDictionary<string, ReadWriteSocketAsyncEventArgsEx> socketReadWriteEventArgsList; /// <summary> /// 用户对象池,用于发送数据 /// </summary> protected ObjectPool<UserToken> writeUserTokenPool; /// <summary> /// 发送线程池 /// </summary> protected ThreadPoolManager sendThreadPool; /// <summary> /// 接收连接事件 /// </summary> public event SocketEventHandler SocketEventAccept; /// <summary> /// /// </summary> public event SocketEventHandler SocketEventConnect; /// <summary> /// 接收数据事件 /// </summary> public event SocketEventHandler SocketEventReceive; /// <summary> /// 断连事件 /// </summary> public event SocketEventHandler SocketEventDisconnect; /// <summary> /// 发送完成事件 /// </summary> public event SocketEventHandler SocketEventSend; public AsyncIocpSocket(int numOfConnections, int readBufferSize, int maxNumberOfClients) { try { this.numOfInitConnections = numOfConnections; this.readBufferSize = readBufferSize; this.numOfListening = numOfListening; bufferManager.InitBuffer(numOfConnections, readBufferSize); socketReadWriteEventArgsList = new SyncDictionary<string, ReadWriteSocketAsyncEventArgsEx>(numOfConnections + BufferManager.INCREMENT_SIZE); socketReadWriteEventArgsList = new SyncDictionary<string, ReadWriteSocketAsyncEventArgsEx>(numOfConnections + BufferManager.INCREMENT_SIZE); socketReadWritePool = new ObjectPool<ReadWriteSocketAsyncEventArgsEx>(); writeUserTokenPool = new ObjectPool<UserToken>(numOfConnections * 5, readBufferSize, -1); int workerMinThreads; int workerMaxThreads; int completionPortThreads; ThreadPool.GetMinThreads(out workerMinThreads, out completionPortThreads); ThreadPool.GetMaxThreads(out workerMaxThreads, out completionPortThreads); sendThreadPool = new ThreadPoolManager(workerMinThreads, workerMaxThreads, int.MaxValue); sendThreadPool.Start(); if (maxNumberOfClients != MAX_ACCEPT_CLIENTS_INFINITE) { isMaxControl = true; maxNumberClients = new Semaphore(maxNumberOfClients, maxNumberOfClients); } ReadWriteSocketAsyncEventArgsEx socketReadWrite; byte[] buffer; for (int i = 0; i < numOfConnections + BufferManager.INCREMENT_SIZE; i++) { socketReadWrite = new ReadWriteSocketAsyncEventArgsEx(); socketReadWrite.writeSocketEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); socketReadWrite.writeSocketEventArgs.UserToken = new UserToken(); ((UserToken)(socketReadWrite.writeSocketEventArgs.UserToken)).SocketId = new SocketId(); socketReadWrite.readSocketEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); socketReadWrite.readSocketEventArgs.UserToken = new UserToken(); buffer = bufferManager.GetAvailableBuffer(); socketReadWrite.readSocketEventArgs.SetBuffer(buffer, 0, buffer.Length); socketReadWritePool.Push(socketReadWrite); } socketReadWritePool.InitCapacity = numOfConnections + BufferManager.INCREMENT_SIZE; } catch(Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } new public void Dispose() { sendThreadPool.Stop(); bufferManager.Clear(); socketReadWritePool.Clear(); socketReadWriteEventArgsList.Clear(); writeUserTokenPool.Clear(); base.Dispose(); } /// <summary> /// 启动监听服务 /// </summary> /// <param name="listenPort"></param> public void Start(int listenPort, int numOfListening) { listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, listenPort); listenSocket.Bind(endPoint); listenSocket.Listen(numOfInitConnections); for (int i = 0; i < numOfListening; i++) { StartAccept(null); } } public void Connect(string serverIp, int port) { SocketAsyncEventArgsEx e = new SocketAsyncEventArgsEx(); IPAddress addr; if(!IPAddress.TryParse(serverIp, out addr)) { IPAddress[] addrs = Dns.GetHostAddresses(serverIp); if(addrs!=null) { if(addrs.Length > 0) { addr = addrs[0]; } } } e.RemoteEndPoint = new IPEndPoint(addr, port); e.Completed += ConnectEventArg_Completed; Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); UserToken userToken = new UserToken(); userToken.SocketId = new SocketId(); userToken.SocketId.Socket = client; userToken.IP = addr.ToString(); userToken.Port = port; e.UserToken = userToken; bool willRaiseEvent = client.ConnectAsync(e); if (!willRaiseEvent) { ProcessConnect(e); } } /// <summary> /// 开始监听 /// </summary> /// <param name="acceptEventArg"></param> protected void StartAccept(SocketAsyncEventArgs acceptEventArg) { if (acceptEventArg == null) { acceptEventArg = new SocketAsyncEventArgsEx(); acceptEventArg.UserToken = new UserToken(); ((UserToken)acceptEventArg.UserToken).SocketId = new SocketId(); acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed); } else { acceptEventArg.AcceptSocket = null; } if (isMaxControl) { try { maxNumberClients.WaitOne(); } catch(Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } try { if (listenSocket != null) { if (acceptEventArg != null) { bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg); if (!willRaiseEvent) { ProcessAccept(acceptEventArg); } } } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } /// <summary> /// 监听接收回调 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) { ProcessAccept(e as SocketAsyncEventArgs); } protected void ConnectEventArg_Completed(object sender, SocketAsyncEventArgs e) { ProcessConnect(e as SocketAsyncEventArgs); } /// <summary> /// 处理监听结果 /// </summary> /// <param name="e"></param> private void ProcessAccept(SocketAsyncEventArgs e) { try { UserToken token = e.UserToken as UserToken; if (e.AcceptSocket != null) { token.SocketId.Socket = e.AcceptSocket; if (e.LastOperation != SocketAsyncOperation.Disconnect) { SocketId socketIdTemp = token.SocketId; UserToken userToken; try { AddConnectedSocket(e, out userToken); if (SocketEventAccept != null) { SocketEventAccept(this, userToken); } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } token.SocketId = socketIdTemp; } } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } finally { StartAccept(e); } } private void ProcessConnect(SocketAsyncEventArgs e) { try { UserToken token = e.UserToken as UserToken; if (e.SocketError == SocketError.Success) { if (e.LastOperation != SocketAsyncOperation.Disconnect) { e.AcceptSocket = token.SocketId.Socket; SocketId socketIdTemp = token.SocketId; UserToken userToken; try { AddConnectedSocket(e, out userToken); if (SocketEventConnect != null) { SocketEventConnect(this, userToken); } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } token.SocketId = socketIdTemp; } } else { if (SocketEventConnect != null) { SocketEventConnect(this, token); } } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } /// <summary> /// 增加连接处理 /// </summary> /// <param name="e"></param> /// <param name="userToken"></param> protected void AddConnectedSocket(SocketAsyncEventArgs e, out UserToken userToken) { if (e == null) { throw new Exception("对象为空"); } userToken = null; ReadWriteSocketAsyncEventArgsEx socketReadWrite = null; UserToken token = e.UserToken as UserToken; if (!socketReadWriteEventArgsList.ContainsKey(token.SocketId.Id)) { socketReadWrite = socketReadWritePool.Pop(); if (socketReadWrite.writeSocketEventArgs.UserToken == null) { socketReadWrite.writeSocketEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); socketReadWrite.writeSocketEventArgs.UserToken = new UserToken(); ((UserToken)(socketReadWrite.writeSocketEventArgs.UserToken)).SocketId = new SocketId(); } ((UserToken)(socketReadWrite.writeSocketEventArgs.UserToken)).SocketId.Socket = e.AcceptSocket; socketReadWriteEventArgsList.Add(((UserToken)(socketReadWrite.writeSocketEventArgs.UserToken)).SocketId.Id, socketReadWrite); if (socketReadWrite.readSocketEventArgs.UserToken == null) { socketReadWrite.readSocketEventArgs.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); socketReadWrite.readSocketEventArgs.UserToken = new UserToken(); byte[] buffer = bufferManager.GetAvailableBuffer(); socketReadWrite.readSocketEventArgs.SetBuffer(buffer, 0, buffer.Length); } ((UserToken)(socketReadWrite.readSocketEventArgs.UserToken)).SocketId = ((UserToken)socketReadWrite.writeSocketEventArgs.UserToken).SocketId; socketReadWriteEventArgsList.Add(((UserToken)(socketReadWrite.readSocketEventArgs.UserToken)).SocketId.Id, socketReadWrite); ((UserToken)(e.UserToken)).SocketId = ((UserToken)(socketReadWrite.readSocketEventArgs.UserToken)).SocketId; sendThreadPool.IncrementUser(((UserToken)(e.UserToken)).SocketId.Id); userToken = (UserToken)socketReadWrite.readSocketEventArgs.UserToken; userToken.SetEndPoint(); bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(socketReadWrite.readSocketEventArgs); if (!willRaiseEvent) { ProcessReceive(socketReadWrite.readSocketEventArgs); } } else { userToken = (UserToken)socketReadWriteEventArgsList[token.SocketId.Id].readSocketEventArgs.UserToken; } } /// <summary> /// IOCP完成处理 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> protected void IO_Completed(object sender, SocketAsyncEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Send: break; case SocketAsyncOperation.Receive: ProcessReceive(e); break; default: throw new ArgumentException("The last operation completed on the socket was not a receive or send"); } } /// <summary> /// 关闭Socket /// </summary> /// <param name="e"></param> /// <param name="isRemoteClose"></param> protected void CloseSocket(SocketAsyncEventArgsEx e, bool isRemoteClose) { if (e == null) { return; } if (e.UserToken == null) { return; } ReadWriteSocketAsyncEventArgsEx socketReadWrite = null; try { UserToken token = e.UserToken as UserToken; if (socketReadWriteEventArgsList.ContainsKey(token.SocketId.Id)) { socketReadWrite = socketReadWriteEventArgsList[token.SocketId.Id]; lock (socketReadWrite.writeSocketEventArgs.LockClose) { if (socketReadWriteEventArgsList.ContainsKey(token.SocketId.Id)) { socketReadWriteEventArgsList.Remove(token.SocketId.Id); } else { return; } } } else { return; } sendThreadPool.DecrementUser(token.SocketId.Id); string ip = SocketUtility.GetHostIPBySocket(token.SocketId.Socket); try { if (token != null) { if (token.SocketId.Socket != null) { if (SocketEventDisconnect != null) { token.IsRemoteClose = isRemoteClose; SocketEventDisconnect(this, token); } token.SocketId.Socket.Close(); } } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } token.SocketId.Socket = null; e.AcceptSocket = null; socketReadWrite.writeSocketEventArgs.SocketFlags = SocketFlags.None; socketReadWrite.readSocketEventArgs.SocketFlags = SocketFlags.None; socketReadWritePool.Push(socketReadWrite); if (isMaxControl) { try { maxNumberClients.Release(); } catch{} } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } /// <summary> /// 关闭Socket /// </summary> /// <param name="socketId"></param> /// <param name="isRemoveClose"></param> public void CloseSocket(SocketId socketId, bool isRemoveClose) { try { if (socketReadWriteEventArgsList.ContainsKey(socketId.Id)) { ReadWriteSocketAsyncEventArgsEx socketReadWrite = socketReadWriteEventArgsList[socketId.Id]; if (socketReadWrite.readSocketEventArgs != null) { CloseSocket(socketReadWrite.readSocketEventArgs, isRemoveClose); } } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } public void CloseAll() { List<ReadWriteSocketAsyncEventArgsEx> socketEventArgsList = new List<ReadWriteSocketAsyncEventArgsEx>(socketReadWriteEventArgsList.Count); foreach (KeyValuePair<string, ReadWriteSocketAsyncEventArgsEx> e in socketReadWriteEventArgsList) { socketEventArgsList.Add(e.Value); } foreach (ReadWriteSocketAsyncEventArgsEx e in socketEventArgsList) { CloseSocket(e.readSocketEventArgs, false); } socketReadWriteEventArgsList.Clear(); } /// <summary> /// 停止监听 /// </summary> /// <param name="stopListen"></param> public void Stop(bool stopListen) { sendThreadPool.Stop(); SocketEventReceive = null; SocketEventDisconnect = null; List<ReadWriteSocketAsyncEventArgsEx> socketEventArgsList = new List<ReadWriteSocketAsyncEventArgsEx>(socketReadWriteEventArgsList.Count); foreach (KeyValuePair<string, ReadWriteSocketAsyncEventArgsEx> e in socketReadWriteEventArgsList) { socketEventArgsList.Add(e.Value); } foreach (ReadWriteSocketAsyncEventArgsEx e in socketEventArgsList) { CloseSocket(e.readSocketEventArgs, false); } socketReadWriteEventArgsList.Clear(); if (stopListen) { try { listenSocket.Close(); } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } listenSocket = null; } } /// <summary> /// 处理接收数据事件 /// </summary> /// <param name="e"></param> protected void ProcessReceive(SocketAsyncEventArgs e) { try { UserToken token = (UserToken)e.UserToken; if (e.BytesTransferred > 0 || SocketUtility.IsNotError(e.SocketError)) { try { if (SocketEventReceive != null) { if (e.BytesTransferred > 0) { token.Buffer = e.Buffer; token.TransferedLength = e.BytesTransferred; SocketEventReceive(this, token); } } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } try { e.SetBuffer(token.Offset, token.Buffer.Length - token.Offset); if (token.SocketId.Socket != null) { if (token.SocketId.Socket.Connected) { bool willRaiseEvent = token.SocketId.Socket.ReceiveAsync(e); if (!willRaiseEvent) { ProcessReceive(e); } } } } catch (InvalidOperationException) { } } else if (e.BytesTransferred == 0) { CloseSocket(e as SocketAsyncEventArgsEx, true); } else { throw new Exception("接收数据失败,错误信息:" + e.SocketError.ToString()); } } catch (Exception ex) { CloseSocket(e as SocketAsyncEventArgsEx, false); Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } } /// <summary> /// 发送线程 /// </summary> /// <param name="param"></param> protected void SendThread(object param) { UserToken userToken = param as UserToken; if (userToken != null) { try { int total = 0; int send = 0; do { if (userToken.SocketId.Socket != null && userToken.SocketId.Socket.Connected) { send = userToken.SocketId.Socket.Send(userToken.Buffer, total, userToken.TransferedLength - total, SocketFlags.None); total += send; } else { userToken.TransferedLength = total; break; } } while (total < userToken.TransferedLength); if (SocketEventSend != null) { SocketEventSend(this, userToken); } } catch (Exception ex) { if (SocketEventSend != null) { userToken.SendSuccess = false; SocketEventSend(this, userToken); } CloseSocket(userToken.SocketId, false); Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } finally { userToken.Reset(); writeUserTokenPool.Push(userToken); } } } /// <summary> /// 异步发送 /// </summary> /// <param name="socketId"></param> /// <param name="data"></param> /// <param name="length"></param> /// <returns></returns> public bool SendAsync(SocketId socketId, byte[] data, int length) { return SendAsync(socketId, data, length, SocketUtility.DefaultUid, SocketUtility.DefaultUid); } /// <summary> /// 异步发送,uidDisconnect表示发送完成后断连的标志 /// </summary> /// <param name="socketId"></param> /// <param name="data"></param> /// <param name="length"></param> /// <param name="uid"></param> /// <param name="uidDisconnect"></param> /// <returns></returns> public bool SendAsync(SocketId socketId, byte[] data, int length, long uid, long uidDisconnect) { bool ret = true; UserToken userToken = null; try { if (socketId.Socket != null) { if (socketId.Socket.Connected) { if (socketReadWriteEventArgsList.ContainsKey(socketId.Id)) { userToken = (UserToken)writeUserTokenPool.Pop(); userToken.SocketId = socketId; userToken.Offset = 0; userToken.TransferedLength = length; userToken.Uid = uid; userToken.UidDisconnect = uidDisconnect; Memory.Copy(ref userToken.Buffer, data, 0, length); sendThreadPool.QueueUserWork(socketId.Id, SendThread, userToken); } } } } catch (Exception ex) { if (userToken != null) { if (SocketEventSend != null) { userToken.SendSuccess = false; SocketEventSend(this, userToken); } userToken.Reset(); writeUserTokenPool.Push(userToken); } ret = false; Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } return ret; } /// <summary> /// 得到Socket对象 /// </summary> /// <param name="socketId"></param> /// <returns></returns> public Socket GetSocketById(string socketId) { Socket socket = null; try { ReadWriteSocketAsyncEventArgsEx socketReadWrite = socketReadWriteEventArgsList[socketId]; if (socketReadWrite.readSocketEventArgs != null) { UserToken token = socketReadWrite.readSocketEventArgs.UserToken as UserToken; socket = token.SocketId.Socket; } } catch (Exception ex) { Tools.Tools.Log.WriteLogError(Tools.Tools.GetExceptionString(GetType(), ex), true); } return socket; } } }