diff options
Diffstat (limited to 'lib/Net.Transport.SimpleTCP/src')
4 files changed, 25 insertions, 24 deletions
diff --git a/lib/Net.Transport.SimpleTCP/src/AwaitableAsyncServerSocket.cs b/lib/Net.Transport.SimpleTCP/src/AwaitableAsyncServerSocket.cs index e830107..1dbaa67 100644 --- a/lib/Net.Transport.SimpleTCP/src/AwaitableAsyncServerSocket.cs +++ b/lib/Net.Transport.SimpleTCP/src/AwaitableAsyncServerSocket.cs @@ -47,19 +47,21 @@ namespace VNLib.Net.Transport.Tcp private Socket? _socket; public readonly SocketPipeLineWorker SocketWorker; + private readonly bool _reuseSocket; private readonly AwaitableValueSocketEventArgs _recvArgs = new(); private readonly AwaitableValueSocketEventArgs _allArgs = new(); private Task _sendTask = Task.CompletedTask; private Task _recvTask = Task.CompletedTask; - public AwaitableAsyncServerSocket(PipeOptions options) : base() + public AwaitableAsyncServerSocket(bool reuseSocket, PipeOptions options) : base() { + _reuseSocket = reuseSocket && IsWindows; //Reuse only available on Windows SocketWorker = new(options); //Set reuse flags now - _recvArgs.DisconnectReuseSocket = IsWindows; - _allArgs.DisconnectReuseSocket = IsWindows; + _recvArgs.DisconnectReuseSocket = _reuseSocket; + _allArgs.DisconnectReuseSocket = _reuseSocket; } @@ -75,11 +77,11 @@ namespace VNLib.Net.Transport.Tcp //get buffer from the pipe to write initial accept data to Memory<byte> buffer = SocketWorker.GetMemory(recvBuffSize); _allArgs.SetBuffer(buffer); - - //Also on windows we can reuse the previous socket if its set - _allArgs.AcceptSocket = _socket; } + //Reuse socket if it's set + _allArgs.AcceptSocket = _socket; + //Begin the accept SocketError error = await _allArgs.AcceptAsync(serverSocket); @@ -129,12 +131,12 @@ namespace VNLib.Net.Transport.Tcp await _recvTask.ConfigureAwait(false); /* - * Sockets are reused as much as possible on Windows. If the socket + * Sockets can be reused as much as possible on Windows. If the socket * failes to disconnect cleanly, the release function won't clean it up * so it needs to be cleaned up here so at least our args instance * can be reused. */ - if(IsWindows && error != SocketError.Success) + if(_reuseSocket && error != SocketError.Success) { _socket.Dispose(); _socket = null; @@ -168,7 +170,7 @@ namespace VNLib.Net.Transport.Tcp void IReusable.Prepare() { - Debug.Assert(_socket == null || IsWindows, "Exepcted stale socket to be NULL on non-Windows platform"); + Debug.Assert(_socket == null || _reuseSocket, "Exepcted stale socket to be NULL on non-Windows platform"); _allArgs.Prepare(); _recvArgs.Prepare(); @@ -184,8 +186,8 @@ namespace VNLib.Net.Transport.Tcp _allArgs.Release(); _recvArgs.Release(); - //if the socket is still 'connected' (or not windows), dispose it and clear the accept socket - if (_socket?.Connected == true || !IsWindows) + //if the socket is still 'connected' (or no reuse), dispose it and clear the accept socket + if (_socket?.Connected == true || !_reuseSocket) { _socket?.Dispose(); _socket = null; diff --git a/lib/Net.Transport.SimpleTCP/src/TCPConfig.cs b/lib/Net.Transport.SimpleTCP/src/TCPConfig.cs index 6bf63d1..886e79d 100644 --- a/lib/Net.Transport.SimpleTCP/src/TCPConfig.cs +++ b/lib/Net.Transport.SimpleTCP/src/TCPConfig.cs @@ -53,10 +53,6 @@ namespace VNLib.Net.Transport.Tcp /// </summary> public required readonly int KeepaliveInterval { get; init; } /// <summary> - /// Enables TCP keepalive - /// </summary> - public required readonly bool TcpKeepalive { get; init; } - /// <summary> /// The maximum number of waiting WSA asynchronous socket accept operations /// </summary> public required readonly uint AcceptThreads { get; init; } @@ -74,6 +70,11 @@ namespace VNLib.Net.Transport.Tcp /// </summary> public required readonly int BackLog { get; init; } /// <summary> + /// Reuse the TCP socket descriptor after a socket has been closed. + /// Only available on Windows platforms. + /// </summary> + public required readonly bool ReuseSocket { get; init; } + /// <summary> /// The <see cref="MemoryPool{T}"/> to allocate transport buffers from /// </summary> public required readonly MemoryPool<byte> BufferPool { get; init; } diff --git a/lib/Net.Transport.SimpleTCP/src/TcpListenerNode.cs b/lib/Net.Transport.SimpleTCP/src/TcpListenerNode.cs index 0badece..665dd42 100644 --- a/lib/Net.Transport.SimpleTCP/src/TcpListenerNode.cs +++ b/lib/Net.Transport.SimpleTCP/src/TcpListenerNode.cs @@ -62,7 +62,7 @@ namespace VNLib.Net.Transport.Tcp //Arguments constructor [MethodImpl(MethodImplOptions.AggressiveInlining)] - AwaitableAsyncServerSocket ArgsConstructor() => new(pipeOptions); + AwaitableAsyncServerSocket ArgsConstructor() => new(Config.ReuseSocket, pipeOptions); SockAsyncArgPool = ObjectRental.CreateReusable(ArgsConstructor, config.CacheQuota); @@ -186,7 +186,7 @@ namespace VNLib.Net.Transport.Tcp bool maxConsReached = _connectedClients > Config.MaxConnections; //Add to waiting queue - if (maxConsReached || !WaitingSockets!.TryEnque(acceptArgs)) + if (maxConsReached || !WaitingSockets!.TryEnqueue(acceptArgs)) { /* * If max connections are reached or the queue is overflowing, diff --git a/lib/Net.Transport.SimpleTCP/src/TcpServer.cs b/lib/Net.Transport.SimpleTCP/src/TcpServer.cs index 5a82298..79d53fe 100644 --- a/lib/Net.Transport.SimpleTCP/src/TcpServer.cs +++ b/lib/Net.Transport.SimpleTCP/src/TcpServer.cs @@ -106,17 +106,13 @@ namespace VNLib.Net.Transport.Tcp /// <exception cref="InvalidOperationException"></exception> public ITcpListner Listen() { - Socket serverSock; - //Configure socket on the current thread so exceptions will be raised to the caller - serverSock = new(_config.LocalEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); + Socket serverSock = new(_config.LocalEndPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); serverSock.Bind(_config.LocalEndPoint); - - serverSock.Listen(_config.BackLog); //See if keepalive should be used - if (_config.TcpKeepalive) + if (_config.TcpKeepAliveTime > 0) { //Setup socket keepalive from config serverSock.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true); @@ -126,7 +122,9 @@ namespace VNLib.Net.Transport.Tcp //Invoke socket created callback _config.OnSocketCreated?.Invoke(serverSock); - + + serverSock.Listen(_config.BackLog); + TcpListenerNode listener = new(in Config, serverSock, _pipeOptions); listener.StartWorkers(); |