Home > Enterprise >  C# TcpClinet LingerOption with Close() not skips TIME_WAIT
C# TcpClinet LingerOption with Close() not skips TIME_WAIT

Time:09-17

I am trying to contact to server with C# TcpClient for lots of time. For example, I connect to server for 5s, disconnect then try connect to server in 10s, and repeat...

But eventhogh I set LingerOption and ResueAddress Option as true, ExtendedSocketExcption came out when I reconnect to server.

Here is my code. (.Net5, Windows 10)

        TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 50010));
        TCPSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
        LingerOption lo = new LingerOption(true, 0);
        TCPSocket.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Linger, lo);

        TCPSocket.Connect(new IPEndPoint("10.10.0.50", 50010));
        TCPSocket.ReceiveTimeout = 5000;
        
        //Do somthing

       TCPSocket.Client.Shutdown(SocketShutdown.Both);
       TCPSocket.Close();
       Thread.Sleep(5000);

       TCPSocket.Connect(new IPEndPoint(SRE3021IP, SRE3021TCPPort)); //ExtendedSocketExeption 

And I check on cmd with command netstat -ano | findstr 50010 while thread was sleeping.

  TCP    10.10.0.100:50010      10.10.0.50:50010       TIME_WAIT       0

The TIME_WAIT state remained about 30~1 min then It disappeared...

I don't know why linger option was not applied.

CodePudding user response:

Setting a LingerOption doesn't stop a socket from closing. It delays the close() to allow any unsent data in the buffer to be sent. This allows an application to move on to the next phase with a slow network. The socket will still close.

ReuseAddress has nothing to do with reusing an existing socket (believe it or not), it allows a Listening Socket to bind to an existing listening port. This is a very bespoke behaviour and requires other process interops to have two different applications listening on the same port. This option has no useful meaning on an outbound socket connection.

Your problem stems from the fact you're setting a source bind with this line:

TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 50010 ));

If you want to set a source port you have no option but to wait for the OS to clean out the socket from the connection list which means waiting for the TIME_WAIT to expire.

If you don't want to set a source port, (and these days their are very few reasons to actually set a source port) but still want to select a specific source IP address interface then you can use:

TCPSocket = new TcpClient(new IPEndPoint("10.10.0.100", 0));

If you want Windows to just choose the most appropriate outgoing interface, (and port), then use:

TCPSocket = new TcpClient();

  • Related