/// <summary> /// Begins a receive operation on <see cref="Socket"/> using the <typeparamref name="T"/> message handler implementation /// </summary> public async Task BeginReceiveAsync <T>(CancellationToken?cancellationToken = null) where T : NetworkMessageHandler { try { if (SerializationHandler == null) { // SerializationHandler must be implemented to transform the network message from binary data to T throw new ArgumentNullException(nameof(SerializationHandler)); } var messageHandler = Activator.CreateInstance <T>(); while (true) { // try receive data from connected socket int bytesTransferred; try { bytesTransferred = await _stream.ReadAsync(messageHandler.Buffer, messageHandler.Offset, messageHandler.Length, cancellationToken ?? _cancellationSource.Token) .ConfigureAwait(false); // to avoid deadlock, continue the execution on any free thread at the time } catch (Exception ex) { if (ex.InnerException is SocketException) { var socketEx = ex.InnerException as SocketException; if (socketEx.SocketErrorCode == SocketError.ConnectionReset || socketEx.SocketErrorCode == SocketError.ConnectionAborted) { // 'ConnectionReset' will happen when the other party has closed the connection unexpectedly ClientHandler?.OnConnectionClosedAsync(this); break; } } // unhandled throw; } if (bytesTransferred == 0) { // zero bytes means the connection has been closed await ClientHandler?.OnConnectionClosedAsync(this); break; } // process the received data in the message handler var isReceiveCompleted = messageHandler.CompleteReceive(bytesTransferred); if (isReceiveCompleted == null) { // invoke the client handler to process the error in the implementation ClientHandler?.OnReceiveError(this, new SocketException((int)SocketError.MessageSize)); continue; } if ((bool)isReceiveCompleted) { // finalize (deobfuscation etc), deserialize to complete message, and process in protocol await ClientHandler?.OnMessageAsync(this, SerializationHandler.Deserialize(messageHandler.GetFinalized())); // message has been processed, so handler can be resetted messageHandler.Reset(); } } } catch (Exception ex) { ClientHandler?.OnReceiveError(this, ex); } }