NetCoreServer icon indicating copy to clipboard operation
NetCoreServer copied to clipboard

TIME_WAIT after TCP socket closing

Open alexsandrbushurov opened this issue 3 years ago • 0 comments

What we have: 2 servers and 2 clients on one PC with next configuration Server1: 127.0.0.1:36000 (Listens for Client2) Client1: connects to Server2 (127.0.0.1:36001) from local point 127.0.0.1:36002

Server2: 127.0.0.1:36001 (Listens for Client1) Client2: connects to Server1 (127.0.0.1:36000) from local point 127.0.0.1:36003

Sockets creation on Client1 and Clients2:

        protected override Socket CreateSocket()
        {
            var socket = base.CreateSocket();
            if (socket == null) return null;
            socket.Bind(new IPEndPoint(_client.IPAddress, _client.Port));
            return socket;
        }

Making some exchange bettween clients

Problem Description Let us have some point of time when Client2 decides to terminate. So, Client2 closes Socket, Server2 closes Socket and all its' sessions. Client1 catches disconnection, and closes Socket too. After that Server1 decides to terminate. All given operations happens at "one time". (netstat -aon shows that some connections are in TIME_WAIT state)

After a couple of seconds Server1 and Client1 starting again, after them Server2 and Client2 starts too. Client2 cathes: SocketException: Address already in use.

Possible solution

        /// <summary>
        /// Sets socket options and parameters
        /// </summary>
        protected virtual void SetSocketOptions()
        {
            // Apply the option: keep alive
            if (OptionKeepAlive) Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
            // Apply the option: no delay
            if (OptionNoDelay) Socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.NoDelay, true);

            // Apply the option: dual mode (this option must be applied before connecting)
            // if (Socket.AddressFamily == AddressFamily.InterNetworkV6)
            //     Socket.DualMode = OptionDualMode;

            Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, new LingerOption(false, 0));
            Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            Socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.DontLinger, true);
        }

Results I have tried some other settings and configurations, but still have the same problem. Some help appreciated.

alexsandrbushurov avatar Dec 25 '20 09:12 alexsandrbushurov