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; BufferDeflector.ReplaceBuffer(_bufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); while (true) { frameLength = 0; payload = null; payloadOffset = 0; payloadCount = 0; if (_configuration.FrameBuilder.Decoder.TryDecodeFrame(_receiveBuffer, 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; } } try { BufferDeflector.ShiftBuffer(_bufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); } catch (ArgumentOutOfRangeException) { } }
private async Task Process() { try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; var saea = _saeaPool.Take(); saea.Saea.SetBuffer(_receiveBuffer, 0, _receiveBuffer.Length); while (State == TcpSocketConnectionState.Connected) { saea.Saea.SetBuffer(0, _receiveBuffer.Length); var socketError = await _socket.ReceiveAsync(saea); if (socketError != SocketError.Success) { break; } var receiveCount = saea.Saea.BytesTransferred; if (receiveCount == 0) { break; } BufferDeflector.AppendBuffer(_bufferManager, ref _receiveBuffer, receiveCount, ref _sessionBuffer, ref _sessionBufferCount); while (true) { if (_configuration.FrameBuilder.TryDecodeFrame(_sessionBuffer, _sessionBufferCount, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { await _dispatcher.OnSessionDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) { HandleUserSideError(ex); } finally { BufferDeflector.ShiftBuffer(_bufferManager, frameLength, ref _sessionBuffer, ref _sessionBufferCount); #if DEBUG _log.DebugFormat("Session [{0}] buffer length [{1}].", this, _sessionBufferCount); #endif } } else { break; } } } } catch (Exception ex) when(!ShouldThrow(ex)) { } finally { await Close(); } }
private async Task Process() { try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; var saea = _saeaPool.Take(); saea.Saea.SetBuffer(_receiveBuffer, _receiveBufferOffset, _receiveBuffer.Length - _receiveBufferOffset); while (State == TcpSocketConnectionState.Connected) { saea.Saea.SetBuffer(_receiveBufferOffset, _receiveBuffer.Length - _receiveBufferOffset); var socketError = await _socket.ReceiveAsync(saea); if (socketError != SocketError.Success) { break; } var receiveCount = saea.Saea.BytesTransferred; if (receiveCount == 0) { break; } BufferDeflector.ReplaceBuffer(_bufferManager, ref _receiveBuffer, ref _receiveBufferOffset, receiveCount); while (true) { if (_configuration.FrameBuilder.TryDecodeFrame(_receiveBuffer, _receiveBufferOffset, out frameLength, out payload, out payloadOffset, out payloadCount)) { try { await _dispatcher.OnSessionDataReceived(this, payload, payloadOffset, payloadCount); } catch (Exception ex) { HandleUserSideError(ex); } finally { try { BufferDeflector.ShiftBuffer(_bufferManager, frameLength, ref _receiveBuffer, ref _receiveBufferOffset); } catch (ArgumentOutOfRangeException) { } } } else { break; } } } } 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; while (State == TcpSocketConnectionState.Connected) { int receiveCount = await _stream.ReadAsync(_receiveBuffer, _receiveBufferOffset, _receiveBuffer.Length - _receiveBufferOffset); if (receiveCount == 0) { break; } BufferDeflector.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, 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 { BufferDeflector.ShiftBuffer(_bufferManager, consumedLength, ref _receiveBuffer, ref _receiveBufferOffset); } catch (ArgumentOutOfRangeException) { } } } catch (Exception ex) when(!ShouldThrow(ex)) { } finally { await Close(); } }