/// <summary> /// Continue receiving body /// </summary> public void ContinueReceivingBody(byte[] buffer, int offset, int length) { //NOTE:: //need to call this method many times until all body receive complete _toBeReceiveData = new SocketReceiveState(buffer, offset, length); beginReceiveData(_toBeReceiveData); }
/// <summary> /// receive data callback /// </summary> /// <param name="result"></param> private void receiveDataCallback(IAsyncResult result) { SocketReceiveState receiveState = (SocketReceiveState)result.AsyncState; int recByte = 0; try { recByte = _workingSocket.EndReceive(result); receiveState.Offset += recByte; if (!_isReceivingHeader) { _receivingProgress.Completed += recByte; } } catch (Exception ex) { onClose(ex); return; } if (recByte > 0) { try { analyzeData(receiveState); } catch (Exception ex) { onClose(ex); return; } } else { onClose(new AsyncSocketException("Connection has been closed")); } }
/// <summary> /// Begin receive data /// </summary> /// <param name="header"></param> /// <param name="buffer"></param> /// <param name="offset"></param> /// <param name="length"></param> public void Receive(IProtocolHeader header, byte[] buffer, int offset, int length) { //the buffer length must large than TRANSFER_BLOCK_LENGTH if (buffer.Length - offset < TRANSFER_BLOCK_LENGTH || length < TRANSFER_BLOCK_LENGTH) { throw new ArgumentException("Buffer length must large than TRANSFER_BLOCK_LENGTH"); } if (_isClosing) { throw new AsyncSocketException("Connection has closed"); } _lastReceiveHeader = header; _toBeReceiveData = new SocketReceiveState(buffer, offset, length); _receivingProgress.Reset(); SocketReceiveState receiveState = new SocketReceiveState( _headerBuffer, 0, _headerBuffer.Length); beginReceiveData(receiveState); }
/// <summary> /// begin receive data /// </summary> private void beginReceiveData(SocketReceiveState receiveState) { try { //calculate the length need to be receive at this time int receiveByte = receiveState.Length - (receiveState.Offset - receiveState.StartIndex); if (receiveByte > TRANSFER_BLOCK_LENGTH) { receiveByte = TRANSFER_BLOCK_LENGTH; } _workingSocket.BeginReceive( receiveState.Data, receiveState.Offset, receiveByte, SocketFlags.None, new AsyncCallback(receiveDataCallback), receiveState); } catch (Exception ex) { onClose(ex); } }
/// <summary> /// analyze the received data /// </summary> /// <param name="receiveState"></param> private void analyzeData(SocketReceiveState receiveState) { //a flag to indicate whether the header/body has received complete bool receiveCompleted = true; if (_isReceivingHeader) { //seek the split-symbol between the header and body int position = seekSplitSymbolPosition(receiveState.Data, receiveState.Offset); if (position < 0) { //continue receive header receiveCompleted = false; if (receiveState.Offset >= HEADER_BUFFER_LENGTH) { onClose(new AsyncSocketException("Header data overflow")); return; } } else { //parse the header string //byte[] headerData = new byte[position]; //Buffer.BlockCopy(receiveState.Data, 0, headerData, 0, headerData.Length); //_lastReceiveHeader.HeaderRawData = headerData; _lastReceiveHeader.SetHeaderRawData(receiveState.Data, 0, position); //raise ReceiveHeaderComplete event ReceiveHeaderCompleteEventArgs arg = new ReceiveHeaderCompleteEventArgs(_lastReceiveHeader); try { ReceiveHeaderComplete(this, arg); //NOTE:: //here, caller must specify the "arg.TotalPlanReceivingLength" value, //to indicate whether continue receive body or not } catch (Exception ex) { onClose(ex); return; } if (arg.TotalPlanReceivingLength > 0) { //need receive body _isReceivingHeader = false; _receivingProgress.Total = arg.TotalPlanReceivingLength; //check this data whether it contains partial body int tailLength = receiveState.Offset - position - 4; if (tailLength > 0) { Buffer.BlockCopy(receiveState.Data, position + 4, _toBeReceiveData.Data, _toBeReceiveData.Offset, tailLength); _toBeReceiveData.Offset += tailLength; _receivingProgress.Completed = tailLength; } //replace the receive state object receiveState = _toBeReceiveData; } } } //to judge if the body has receive complete if (!_isReceivingHeader) { if (receiveState.Offset - receiveState.StartIndex < receiveState.Length && _receivingProgress.Completed < _receivingProgress.Total) { //not complete yet receiveCompleted = false; } else { //receive body complete if (_receivingProgress.Completed >= _receivingProgress.Total) { //all body receive complete, reset this flag _isReceivingHeader = true; } //raise the ReceiveBodyComplete event ReceiveBodyCompleteEventArgs arg = new ReceiveBodyCompleteEventArgs( _lastReceiveHeader, receiveState.Data, receiveState.Offset, receiveState.StartIndex, _receivingProgress.Completed, _receivingProgress.Total); try { ReceiveBodyComplete(this, arg); } catch (Exception ex) { onClose(ex); return; } } } //continue to receiving header or body data if (!receiveCompleted) { beginReceiveData(receiveState); } }