private void ReceiveBuffer(int receiveCount) { // TCP guarantees delivery of all packets in the correct order. // But there is no guarantee that one write operation on the sender-side will result in // one read event on the receiving side. One call of write(message) by the sender // can result in multiple messageReceived(session, message) events on the receiver; // and multiple calls of write(message) can lead to a single messageReceived event. // In a stream-based transport such as TCP/IP, received data is stored into a socket receive buffer. // Unfortunately, the buffer of a stream-based transport is not a queue of packets but a queue of bytes. // It means, even if you sent two messages as two independent packets, // an operating system will not treat them as two messages but as just a bunch of bytes. // Therefore, there is no guarantee that what you read is exactly what your remote peer wrote. // There are three common techniques for splitting the stream of bytes into messages: // 1. use fixed length messages // 2. use a fixed length header that indicates the length of the body // 3. using a delimiter; for example many text-based protocols append // a newline (or CR LF pair) after every message. int frameLength; byte[] payload; int payloadOffset; int payloadCount; int consumedLength = 0; SegmentBufferDeflector.ReplaceBuffer(_bufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); while (true) { frameLength = 0; payload = null; payloadOffset = 0; payloadCount = 0; if (_configuration.FrameBuilder.Decoder.TryDecodeFrame( _receiveBuffer.Array, _receiveBuffer.Offset + consumedLength, _receiveBufferOffset - consumedLength, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { _server.RaiseClientDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) { HandleUserSideError(ex); } finally { consumedLength += frameLength; } } else { break; } } SegmentBufferDeflector.ShiftBuffer(_bufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); }
private async Task Process() { try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; int consumedLength = 0; while (State == TcpSocketConnectionState.Connected) { int receiveCount = await _stream.ReadAsync( _receiveBuffer.Array, _receiveBuffer.Offset + _receiveBufferOffset, _receiveBuffer.Count - _receiveBufferOffset); if (receiveCount == 0) { break; } SegmentBufferDeflector.ReplaceBuffer(_bufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); consumedLength = 0; while (true) { frameLength = 0; payload = null; payloadOffset = 0; payloadCount = 0; if (_configuration.FrameBuilder.Decoder.TryDecodeFrame( _receiveBuffer.Array, _receiveBuffer.Offset + consumedLength, _receiveBufferOffset - consumedLength, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { await _dispatcher.OnSessionDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) // catch all exceptions from out-side { await HandleUserSideError(ex); } finally { consumedLength += frameLength; } } else { break; } } if (_receiveBuffer != null && _receiveBuffer.Array != null) { SegmentBufferDeflector.ShiftBuffer(_bufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); } } } catch (ObjectDisposedException) { // looking forward to a graceful quit from the ReadAsync but the inside EndRead will raise the ObjectDisposedException, // so a gracefully close for the socket should be a Shutdown, but we cannot avoid the Close triggers this happen. } catch (Exception ex) { await HandleReceiveOperationException(ex); } finally { await Close(true); // read async buffer returned, remote notifies closed } }
private async Task Process() { try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; int consumedLength = 0; var saea = _saeaPool.Take(); saea.Saea.SetBuffer(_receiveBuffer.Array, _receiveBuffer.Offset + _receiveBufferOffset, _receiveBuffer.Count - _receiveBufferOffset); while (State == TcpSocketConnectionState.Connected) { saea.Saea.SetBuffer(_receiveBuffer.Array, _receiveBuffer.Offset + _receiveBufferOffset, _receiveBuffer.Count - _receiveBufferOffset); var socketError = await _socket.ReceiveAsync(saea); if (socketError != SocketError.Success) { break; } var receiveCount = saea.Saea.BytesTransferred; if (receiveCount == 0) { break; } SegmentBufferDeflector.ReplaceBuffer(_configuration.BufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); consumedLength = 0; while (true) { frameLength = 0; payload = null; payloadOffset = 0; payloadCount = 0; if (_configuration.FrameBuilder.Decoder.TryDecodeFrame(_receiveBuffer.Array, _receiveBuffer.Offset + consumedLength, _receiveBufferOffset - consumedLength, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { await _dispatcher.OnServerDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) { HandleUserSideError(ex); } finally { consumedLength += frameLength; } } else { break; } } try { SegmentBufferDeflector.ShiftBuffer(_configuration.BufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); } catch (ArgumentOutOfRangeException) { } } } catch (Exception ex) when(!ShouldThrow(ex)) { } finally { await Close(); } }
private async Task Process() { try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; int consumedLength = 0; var saea = _saeaPool.Take(); saea.Saea.SetBuffer(_receiveBuffer.Array, _receiveBuffer.Offset + _receiveBufferOffset, _receiveBuffer.Count - _receiveBufferOffset); while (State == TcpSocketConnectionState.Connected) { saea.Saea.SetBuffer(_receiveBuffer.Array, _receiveBuffer.Offset + _receiveBufferOffset, _receiveBuffer.Count - _receiveBufferOffset); var socketError = await _socket.ReceiveAsync(saea); if (socketError != SocketError.Success) { break; } var receiveCount = saea.Saea.BytesTransferred; if (receiveCount == 0) { break; } SegmentBufferDeflector.ReplaceBuffer(_configuration.BufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); consumedLength = 0; while (true) { frameLength = 0; payload = null; payloadOffset = 0; payloadCount = 0; if (_configuration.FrameBuilder.Decoder.TryDecodeFrame(_receiveBuffer.Array, _receiveBuffer.Offset + consumedLength, _receiveBufferOffset - consumedLength, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { await _dispatcher.OnServerDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) // catch all exceptions from out-side { await HandleUserSideError(ex); } finally { consumedLength += frameLength; } } else { break; } } if (_receiveBuffer != null && _receiveBuffer.Array != null) { SegmentBufferDeflector.ShiftBuffer(_configuration.BufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); } } } catch (Exception ex) { await HandleReceiveOperationException(ex); } finally { await Close(true); // read async buffer returned, remote notifies closed } }
private async Task Process() { try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; int consumedLength = 0; while (State == TcpSocketConnectionState.Connected) { int receiveCount = await _stream.ReadAsync(_receiveBuffer.Array, _receiveBuffer.Offset + _receiveBufferOffset, _receiveBuffer.Count - _receiveBufferOffset); if (receiveCount == 0) { break; } SegmentBufferDeflector.ReplaceBuffer(_bufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); consumedLength = 0; while (true) { frameLength = 0; payload = null; payloadOffset = 0; payloadCount = 0; if (_configuration.FrameBuilder.Decoder.TryDecodeFrame( _receiveBuffer.Array, _receiveBuffer.Offset + consumedLength, _receiveBufferOffset - consumedLength, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { await _dispatcher.OnSessionDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) { await HandleUserSideError(ex); } finally { consumedLength += frameLength; } } else { break; } } SegmentBufferDeflector.ShiftBuffer(_bufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); } } catch (Exception ex) { await HandleReceiveOperationException(ex); } finally { await Close(); } }