private void ProcessMessage(byte[] messageData, AsyncUserToken token, SocketAsyncEventArgs e) { var current = Interlocked.Increment(ref _receivedMessageCount); if (current == 1) { _watch = Stopwatch.StartNew(); } if (current % 10000 == 0) { Console.WriteLine("received message, length:{0}, count:{1}, timeSpent:{2}", messageData.Length, current, _watch.ElapsedMilliseconds); } sendingQueue.Add(new MessageData { Message = messageData, Token = token }); }
private void ProcessReceive(SocketAsyncEventArgs e) { if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { AsyncUserToken token = e.UserToken as AsyncUserToken; //处理接收到的数据 ProcessReceivedData(token.DataStartOffset, token.NextReceiveOffset - token.DataStartOffset + e.BytesTransferred, 0, token, e); //更新下一个要接收数据的起始位置 token.NextReceiveOffset += e.BytesTransferred; //如果达到缓冲区的结尾,则将NextReceiveOffset复位到缓冲区起始位置,并迁移可能需要迁移的未处理的数据 if (token.NextReceiveOffset == e.Buffer.Length) { //将NextReceiveOffset复位到缓冲区起始位置 token.NextReceiveOffset = 0; //如果还有未处理的数据,则把这些数据迁移到数据缓冲区的起始位置 if (token.DataStartOffset < e.Buffer.Length) { var notYesProcessDataSize = e.Buffer.Length - token.DataStartOffset; Buffer.BlockCopy(e.Buffer, token.DataStartOffset, e.Buffer, 0, notYesProcessDataSize); //数据迁移到缓冲区起始位置后,需要再次更新NextReceiveOffset token.NextReceiveOffset = notYesProcessDataSize; } token.DataStartOffset = 0; } //更新接收数据的缓冲区下次接收数据的起始位置和最大可接收数据的长度 e.SetBuffer(token.NextReceiveOffset, e.Buffer.Length - token.NextReceiveOffset); //接收后续的数据 if (!token.Socket.ReceiveAsync(e)) { ProcessReceive(e); } } else { CloseClientSocket(e); } }
/// <summary> /// This method is invoked when an asynchronous send operation completes. The method issues another receive /// on the socket to read any additional data sent from the client /// </summary> /// <param name="e"></param> private void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { // done echoing data back to the client AsyncUserToken token = (AsyncUserToken)e.UserToken; // read the next block of data send from the client bool willRaiseEvent = token.Socket.ReceiveAsync(e); if (!willRaiseEvent) { ProcessReceive(e); } } else { CloseClientSocket(e); } }
private void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e.UserToken as AsyncUserToken; // close the socket associated with the client try { token.Socket.Shutdown(SocketShutdown.Send); } // throws if client process has already closed catch (Exception) { } token.Socket.Close(); // decrement the counter keeping track of the total number of clients connected to the server Interlocked.Decrement(ref m_numConnectedSockets); m_maxNumberAcceptedClients.Release(); Console.WriteLine("A client has been disconnected from the server. There are {0} clients connected to the server", m_numConnectedSockets); // Free the SocketAsyncEventArg so they can be reused by another client m_readWritePool.Push(e); }
/// <summary> /// This method is invoked when an asycnhronous receive operation completes. If the /// remote host closed the connection, then the socket is closed. If data was received then /// the data is echoed back to the client. /// </summary> private void ProcessReceive(SocketAsyncEventArgs e) { // check if the remote host closed the connection AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { //increment the count of the total bytes receive by the server Interlocked.Add(ref m_totalBytesRead, e.BytesTransferred); Console.WriteLine("The server has read a total of {0} bytes", m_totalBytesRead); //echo the data received back to the client bool willRaiseEvent = token.Socket.SendAsync(e); if (!willRaiseEvent) { ProcessSend(e); } } else { CloseClientSocket(e); } }
private void ProcessReceivedData(int dataStartOffset, int totalReceivedDataSize, int alreadyProcessedDataSize, AsyncUserToken token, SocketAsyncEventArgs e) { if (alreadyProcessedDataSize >= totalReceivedDataSize) { return; } if (token.MessageSize == null) { //如果之前接收到到数据加上当前接收到的数据大于消息头的大小,则可以解析消息头 if (totalReceivedDataSize > MessageHeaderSize) { //解析消息长度 var headerData = new byte[MessageHeaderSize]; Buffer.BlockCopy(e.Buffer, dataStartOffset, headerData, 0, MessageHeaderSize); var messageSize = BitConverter.ToInt32(headerData, 0); token.MessageSize = messageSize; token.DataStartOffset = dataStartOffset + MessageHeaderSize; //递归处理 ProcessReceivedData(token.DataStartOffset, totalReceivedDataSize, alreadyProcessedDataSize + MessageHeaderSize, token, e); } //如果之前接收到到数据加上当前接收到的数据仍然没有大于消息头的大小,则需要继续接收后续的字节 else { //这里不需要做什么事情 } } else { var messageSize = token.MessageSize.Value; //判断当前累计接收到的字节数减去已经处理的字节数是否大于消息的长度,如果大于,则说明可以解析消息了 if (totalReceivedDataSize - alreadyProcessedDataSize >= messageSize) { var messageData = new byte[messageSize]; Buffer.BlockCopy(e.Buffer, dataStartOffset, messageData, 0, messageSize); ProcessMessage(messageData, token, e); //消息处理完后,需要清理token,以便接收下一个消息 token.DataStartOffset = dataStartOffset + messageSize; token.MessageSize = null; //递归处理 ProcessReceivedData(token.DataStartOffset, totalReceivedDataSize, alreadyProcessedDataSize + messageSize, token, e); } //说明剩下的字节数还不够转化为消息,则需要继续接收后续的字节 else { //这里不需要做什么事情 } } }