diff --git a/source/NetCoreServer/TcpClient.cs b/source/NetCoreServer/TcpClient.cs index 66f5fd90..a6aede11 100644 --- a/source/NetCoreServer/TcpClient.cs +++ b/source/NetCoreServer/TcpClient.cs @@ -147,6 +147,14 @@ private TcpClient(EndPoint endpoint, string address, int port) /// public int OptionSendBufferSize { get; set; } = 8192; + /// + /// Option: whether to send all remaining bytes when disconnecting + /// + /// + /// This only affects bytes end via SendAsync(...) + /// + public bool OptionSendRemainingBytesOnDisconnect { get; set; } = false; + #region Connect/Disconnect client private SocketAsyncEventArgs _connectEventArg; @@ -297,6 +305,12 @@ public virtual bool Disconnect() if (IsConnecting) Socket.CancelConnectAsync(_connectEventArg); + // Wait for pending asynchronous send operations if desired + if (OptionSendRemainingBytesOnDisconnect) + { + _sendBuffersEmpty.WaitOne(); + } + // Reset event args _connectEventArg.Completed -= OnAsyncCompleted; _receiveEventArg.Completed -= OnAsyncCompleted; @@ -440,6 +454,7 @@ public virtual bool ReconnectAsync() private Buffer _sendBufferFlush; private SocketAsyncEventArgs _sendEventArg; private long _sendBufferFlushOffset; + private readonly ManualResetEvent _sendBuffersEmpty = new ManualResetEvent(true); /// /// Send data to the server (synchronous) @@ -544,6 +559,7 @@ public virtual bool SendAsync(ReadOnlySpan buffer) } // Fill the main send buffer + _sendBuffersEmpty.Reset(); _sendBufferMain.Append(buffer); // Update statistic @@ -714,6 +730,8 @@ private void TrySend() // Call the empty send buffer handler if (empty) { + _sendBuffersEmpty.Set(); + OnEmpty(); return; } @@ -928,6 +946,8 @@ private bool ProcessSend(SocketAsyncEventArgs e) return true; else { + _sendBuffersEmpty.Set(); + SendError(e.SocketError); DisconnectAsync(); return false; @@ -1053,6 +1073,7 @@ protected virtual void Dispose(bool disposingManagedResources) { // Dispose managed resources here... DisconnectAsync(); + _sendBuffersEmpty.Dispose(); } // Dispose unmanaged resources here... diff --git a/source/NetCoreServer/TcpSession.cs b/source/NetCoreServer/TcpSession.cs index 6eb65a71..c9f9c728 100644 --- a/source/NetCoreServer/TcpSession.cs +++ b/source/NetCoreServer/TcpSession.cs @@ -71,6 +71,14 @@ public TcpSession(TcpServer server) /// public int OptionSendBufferSize { get; set; } = 8192; + /// + /// Option: whether to send all remaining bytes when disconnecting + /// + /// + /// This only affects bytes end via SendAsync(...) + /// + public bool OptionSendRemainingBytesOnDisconnect { get; set; } = false; + #region Connect/Disconnect session /// @@ -160,6 +168,12 @@ public virtual bool Disconnect() if (!IsConnected) return false; + // Wait for pending asynchronous send operations if desired + if (OptionSendRemainingBytesOnDisconnect) + { + _sendBuffersEmpty.WaitOne(); + } + // Reset event args _receiveEventArg.Completed -= OnAsyncCompleted; _sendEventArg.Completed -= OnAsyncCompleted; @@ -231,6 +245,7 @@ public virtual bool Disconnect() private Buffer _sendBufferFlush; private SocketAsyncEventArgs _sendEventArg; private long _sendBufferFlushOffset; + private readonly ManualResetEvent _sendBuffersEmpty = new ManualResetEvent(true); /// /// Send data to the client (synchronous) @@ -336,6 +351,7 @@ public virtual bool SendAsync(ReadOnlySpan buffer) } // Fill the main send buffer + _sendBuffersEmpty.Reset(); _sendBufferMain.Append(buffer); // Update statistic @@ -507,6 +523,8 @@ private void TrySend() // Call the empty send buffer handler if (empty) { + _sendBuffersEmpty.Set(); + OnEmpty(); return; } @@ -662,6 +680,8 @@ private bool ProcessSend(SocketAsyncEventArgs e) return true; else { + _sendBuffersEmpty.Set(); + SendError(e.SocketError); Disconnect(); return false; @@ -787,6 +807,7 @@ protected virtual void Dispose(bool disposingManagedResources) { // Dispose managed resources here... Disconnect(); + _sendBuffersEmpty.Dispose(); } // Dispose unmanaged resources here...