SocketAsyncEventArgs CreateArgs() { var args = new SocketAsyncEventArgs(); args.Completed += IO_Completed; var token = new AsyncUserToken { Buffer = new byte[SocketConfig.TcpReaderBufferSize] }; args.UserToken = token; args.SetBuffer(token.Buffer, 0, SocketConfig.TcpReaderBufferSize); return(args); }
// This method is invoked when an asynchronous receive operation (by the socket) completes. // If the remote host already closed the connection, then the socket is already closed and we just decrement the counter. // If SocketError.Success, we process the client command and reply immediately (we always send an 'ack'). void ProcessReceive(SocketAsyncEventArgs e) { AsyncUserToken token = (AsyncUserToken)e.UserToken; if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { try { NOTLSEnvelopeExtensions.UpdatePayload(e.BytesTransferred, token); do { NOTLSEnvelope packet = NOTLSEnvelopeExtensions.TryTakeOnePacket(ref token.Payload); if (packet == null) // null -> not yet complete { if (!token.Socket.ReceiveAsync(e)) { ProcessReceive(e); } return; } var clientInformation = token.Socket.RemoteEndPoint.ToString(); byte[] reply = this.requestHandler.ProcessRequestAsync(packet.Serialize(), clientInformation).Result; if (reply != null) { SocketAsyncEventArgs sendArgs = CreateArgs(); ((AsyncUserToken)sendArgs.UserToken).Socket = token.Socket; sendArgs.SetBuffer(reply, 0, reply.Length); if (!token.Socket.SendAsync(sendArgs)) { ProcessSend(sendArgs); } } } while (token.Payload != null); } catch (Exception ex) { this.logger.LogError($"ProcessReceive - {ex}"); } } else { CloseClientSocket(e); } }
void CloseClientSocket(SocketAsyncEventArgs e) { AsyncUserToken token = e?.UserToken as AsyncUserToken; try { if (token == null || token.Socket == null) { #if DEBUG this.logger.LogInformation("CloseClientSocket - token or token.Socket was null. Doing nothing."); #endif return; } try { token.Socket.Shutdown(SocketShutdown.Send); } catch (Exception ex) // throws if client process has already closed { this.logger.LogError($"CloseClientSocket - Socket.Shutdown(SocketShutdown.Send) - {ex.Message}"); } try { token.Socket.Dispose(); } catch (Exception ex) { this.logger.LogError($"CloseClientSocket - Socket.Dispose() - {ex.Message}"); } } finally { // decrement connection counter Interlocked.Decrement(ref NumConnectedSockets); this.maxNumberAcceptedClients.Release(); } #if DEBUG this.logger.LogInformation($"Socket closed, {NumConnectedSockets} connected sockets."); #endif // Once we use the buffer manager: // Free the SocketAsyncEventArg for reuse by another client // readWritePool.Push(e); }
void ProcessSend(SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { // done writing to the client AsyncUserToken token = (AsyncUserToken)e.UserToken; SocketAsyncEventArgs readArgs = CreateArgs(); ((AsyncUserToken)readArgs.UserToken).Socket = token.Socket; // copy the _right_ socket // read the next message from the client bool willRaiseEvent = token.Socket.ReceiveAsync(readArgs); if (!willRaiseEvent) { ProcessReceive(readArgs); } } else { CloseClientSocket(e); } }