I study an example from MSDN:
Server
class Server { private int m_numConnections; private int m_receiveBufferSize; BufferManager m_bufferManager; const int opsToPreAlloc = 2; Socket listenSocket; SocketAsyncEventArgsPool m_readWritePool; int m_totalBytesRead; int m_numConnectedSockets; Semaphore m_maxNumberAcceptedClients; public Server(int numConnections, int receiveBufferSize) { m_totalBytesRead = 0; m_numConnectedSockets = 0; m_numConnections = numConnections; m_receiveBufferSize = receiveBufferSize; m_bufferManager = new BufferManager(receiveBufferSize * numConnections * opsToPreAlloc, receiveBufferSize); m_readWritePool = new SocketAsyncEventArgsPool(numConnections); m_maxNumberAcceptedClients = new Semaphore(numConnections, numConnections); } public void Init() { m_bufferManager.InitBuffer(); SocketAsyncEventArgs readWriteEventArg; for (int i = 0; i < m_numConnections; i++) { readWriteEventArg = new SocketAsyncEventArgs(); readWriteEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(IO_Completed); readWriteEventArg.UserToken = new AsyncUserToken(); m_bufferManager.SetBuffer(readWriteEventArg); m_readWritePool.Push(readWriteEventArg); } } public void Start(IPEndPoint localEndPoint) { listenSocket = new Socket(localEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); listenSocket.Bind(localEndPoint); listenSocket.Listen(100); StartAccept(null); } public void StartAccept(SocketAsyncEventArgs acceptEventArg) { if (acceptEventArg == null) { acceptEventArg = new SocketAsyncEventArgs(); acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed); } else { acceptEventArg.AcceptSocket = null; } m_maxNumberAcceptedClients.WaitOne(); bool willRaiseEvent = listenSocket.AcceptAsync(acceptEventArg); if (!willRaiseEvent) { ProcessAccept(acceptEventArg); } } void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e) { ProcessAccept(e); } private void ProcessAccept(SocketAsyncEventArgs e) { Interlocked.Increment(ref m_numConnectedSockets); SocketAsyncEventArgs readEventArgs = m_readWritePool.Pop(); ((AsyncUserToken)readEventArgs.UserToken).Socket = e.AcceptSocket; bool willRaiseEvent = e.AcceptSocket.ReceiveAsync(readEventArgs); if (!willRaiseEvent) { ProcessReceive(readEventArgs); } StartAccept(e); } void IO_Completed(object sender, SocketAsyncEventArgs e) { switch (e.LastOperation) { case SocketAsyncOperation.Receive: ProcessReceive(e); break; case SocketAsyncOperation.Send: ProcessSend(e); break; default: throw new ArgumentException("The last operation completed on the socket was not a receive or send"); } } private void ProcessReceive(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); e.SetBuffer(e.Offset, e.BytesTransferred); bool willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { ProcessSend(e); } } else { CloseClientSocket(e); } } private void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { AsyncUserToken token = (AsyncUserToken)e.UserToken; bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { ProcessReceive(e); } } else { CloseClientSocket(e); } } private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e.UserToken as AsyncUserToken; try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception) { } token.Socket.Close(); Interlocked.Decrement(ref m_numConnectedSockets); m_maxNumberAcceptedClients.Release(); m_readWritePool.Push(e); } } SocketAsyncEventArgsPool
class SocketAsyncEventArgsPool { Stack<SocketAsyncEventArgs> m_pool; public SocketAsyncEventArgsPool(int capacity) { m_pool = new Stack<SocketAsyncEventArgs>(capacity); } public void Push(SocketAsyncEventArgs item) { if (item == null) { throw new ArgumentNullException("Items added to a SocketAsyncEventArgsPool cannot be null"); } lock (m_pool) { m_pool.Push(item); } } public SocketAsyncEventArgs Pop() { lock (m_pool) { return m_pool.Pop(); } } public int Count { get { return m_pool.Count; } } } BufferManager
class BufferManager { int m_numBytes; byte[] m_buffer; Stack<int> m_freeIndexPool; int m_currentIndex; int m_bufferSize; public BufferManager(int totalBytes, int bufferSize) { m_numBytes = totalBytes; m_currentIndex = 0; m_bufferSize = bufferSize; m_freeIndexPool = new Stack<int>(); } public void InitBuffer() { m_buffer = new byte[m_numBytes]; } public bool SetBuffer(SocketAsyncEventArgs args) { if (m_freeIndexPool.Count > 0) { args.SetBuffer(m_buffer, m_freeIndexPool.Pop(), m_bufferSize); } else { if ((m_numBytes - m_bufferSize) < m_currentIndex) { return false; } args.SetBuffer(m_buffer, m_currentIndex, m_bufferSize); m_currentIndex += m_bufferSize; } return true; } public void FreeBuffer(SocketAsyncEventArgs args) { m_freeIndexPool.Push(args.Offset); args.SetBuffer(null, 0, 0); } } internal class AsyncUserToken { public System.Net.Sockets.Socket Socket { get; set; } } Sortu here use Stack, I have a question, how to work with each socket separately? How to identify the connection and for example to disconnect? I will be glad to help
Cycle
public void sendToAll() { foreach(SocketAsyncEventArgs eventargs in m_pool) { AsyncUserToken token = eventargs.UserToken as AsyncUserToken; token.Socket.Send(Encoding.ASCII.GetBytes("Test")); } }