C# TcpClinet LingerOption with Close() 不跳过 TIME_WAIT

C# TcpClinet LingerOption with Close() not skips TIME_WAIT

我尝试使用 C# TcpClient 连接服务器已有很多时间。例如,我连接到服务器 5 秒,断开连接,然后在 10 秒后尝试连接到服务器,然后重复...

但是尽管如此,我将 LingerOption 和 ResueAddress 选项设置为 true,当我重新连接到服务器时,ExtendedSocketExcption 出现了。

这是我的代码。 (.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 

我在线程休眠时使用命令 netstat -ano | findstr 50010 检查 cmd。

  TCP    10.10.0.100:50010      10.10.0.50:50010       TIME_WAIT       0

TIME_WAIT状态保持了大约30~1分钟然后就消失了...

我不知道为什么没有应用 linger 选项。

设置 LingerOption 不会阻止套接字关闭。它延迟 close() 以允许发送缓冲区中任何未发送的数据。这允许应用程序在网络速度较慢的情况下进入下一阶段。套接字仍会关闭。

ReuseAddress 与重用现有套接字无关(信不信由你),它允许侦听套接字绑定到现有侦听端口。这是一种非常定制的行为,需要其他进程互操作让两个不同的应用程序侦听同一端口。此选项对出站套接字连接没有用处。

您的问题源于您正在使用此行设置源绑定:

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

如果您想设置源端口,您别无选择,只能等待 OS 从连接列表中清除套接字,这意味着等待 TIME_WAIT 过期。

如果您不想设置源端口(现在很少有理由设置源端口)但仍想 select 特定的源 IP 地址接口,那么您可以使用:

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

如果您希望 Windows 只选择最合适的传出接口(和端口),则使用:

TCPSocket = new TcpClient();