private async Task Accept() { try { while (IsListening) { var saea = _acceptSaeaPool.Take(); var socketError = await _listener.AcceptAsync(saea); if (socketError == SocketError.Success) { var acceptedSocket = saea.Saea.AcceptSocket; Task.Factory.StartNew(async() => { await Process(acceptedSocket); }, TaskCreationOptions.None) .Forget(); } else { _log.ErrorFormat("Error occurred when accept incoming socket [{0}].", socketError); } _acceptSaeaPool.Return(saea); } } catch (Exception ex) when(!ShouldThrow(ex)) { } catch (Exception ex) { _log.Error(ex.Message, ex); } }
public async Task Connect() { int origin = Interlocked.Exchange(ref _state, _connecting); if (!(origin == _none || origin == _closed)) { await Close(false); // connecting with wrong state throw new InvalidOperationException("This tcp socket client is in invalid state when connecting."); } Clean(); // force to clean var saea = _saeaPool.Take(); try { _socket = new Socket(SocketType.Stream, ProtocolType.Tcp); SetSocketOptions(); if (_localEndPoint != null) { _socket.Bind(_localEndPoint); } saea.Saea.RemoteEndPoint = _remoteEndPoint; var socketError = await _socket.ConnectAsync(saea); if (socketError != SocketError.Success) { throw new SocketException((int)socketError); } if (_receiveBuffer == default(ArraySegment <byte>)) { _receiveBuffer = _configuration.BufferManager.BorrowBuffer(); } _receiveBufferOffset = 0; if (Interlocked.CompareExchange(ref _state, _connected, _connecting) != _connecting) { await Close(false); // connected with wrong state throw new InvalidOperationException("This tcp socket client is in invalid state when connected."); } _log.DebugFormat("Connected to server [{0}] with dispatcher [{1}] on [{2}].", this.RemoteEndPoint, _dispatcher.GetType().Name, DateTime.UtcNow.ToString(@"yyyy-MM-dd HH:mm:ss.fffffff")); bool isErrorOccurredInUserSide = false; try { await _dispatcher.OnServerConnected(this); } catch (Exception ex) // catch all exceptions from out-side { isErrorOccurredInUserSide = true; await HandleUserSideError(ex); } if (!isErrorOccurredInUserSide) { Task.Factory.StartNew(async() => { await Process(); }, TaskCreationOptions.None) .Forget(); } else { await Close(true); // user side handle tcp connection error occurred } } catch (Exception ex) // catch exceptions then log then re-throw { _log.Error(ex.Message, ex); await Close(true); // handle tcp connection error occurred throw; } finally { _saeaPool.Return(saea); } }
private async Task Process() { var saea = _saeaPool.Take(); try { int frameLength; byte[] payload; int payloadOffset; int payloadCount; int consumedLength = 0; 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(_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 (Exception ex) { await HandleReceiveOperationException(ex); } finally { await Close(true); // read async buffer returned, remote closed _saeaPool.Return(saea); } }