private void AsyncReceive(object state) { while (true) { byte[] readBuffer; lock (_readBuffers) { if (_readBuffers.Count == 0) { lock (_readingMessagesLock) { _readingMessages = false; } return; } readBuffer = _readBuffers.Dequeue(); } _readableDataLen += readBuffer.Length; bool process = true; while (process) { switch (_receiveState) { case ReceiveType.Header: { if (_payloadBuffer == null) { _payloadBuffer = new byte[HEADER_SIZE]; } if (_readableDataLen + _writeOffset >= HEADER_SIZE) { // completely received header int headerLength = HEADER_SIZE - _writeOffset; try { Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, headerLength); _payloadLen = BitConverter.ToInt32(_payloadBuffer, _readOffset); if (_payloadLen <= 0 || _payloadLen > MAX_MESSAGE_SIZE) { throw new Exception("invalid header"); } // try to re-use old payload buffers which fit if (_payloadBuffer.Length <= _payloadLen + HEADER_SIZE) { Array.Resize(ref _payloadBuffer, _payloadLen + HEADER_SIZE); } } catch (Exception) { process = false; Disconnect(); break; } _readableDataLen -= headerLength; _writeOffset += headerLength; _readOffset += headerLength; _receiveState = ReceiveType.Payload; } else // _readableDataLen + _writeOffset < HeaderSize { // received only a part of the header try { Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, _readableDataLen); } catch (Exception) { process = false; Disconnect(); break; } _readOffset += _readableDataLen; _writeOffset += _readableDataLen; process = false; // nothing left to process } break; } case ReceiveType.Payload: { int length = (_writeOffset - HEADER_SIZE + _readableDataLen) >= _payloadLen ? _payloadLen - (_writeOffset - HEADER_SIZE) : _readableDataLen; try { Array.Copy(readBuffer, _readOffset, _payloadBuffer, _writeOffset, length); } catch (Exception) { process = false; Disconnect(); break; } _writeOffset += length; _readOffset += length; _readableDataLen -= length; if (_writeOffset - HEADER_SIZE == _payloadLen) { // completely received payload try { using (PayloadReader pr = new PayloadReader(_payloadBuffer, _payloadLen + HEADER_SIZE, false)) { IMessage message = pr.ReadMessage(); OnClientRead(message, _payloadBuffer.Length); } } catch (Exception) { process = false; Disconnect(); break; } _receiveState = ReceiveType.Header; _payloadLen = 0; _writeOffset = 0; } if (_readableDataLen == 0) { process = false; } break; } } } _readOffset = 0; _readableDataLen = 0; } }