端口被卡在 TIME_WAIT 状态

4
我有一个用C#编写的TCP隧道。我需要打开和关闭该应用程序,该应用程序在服务器和客户端之间进行通信。我使用它来关闭数据连接以测试另一个应用程序。我必须使用特定的端口。
在第二个、第三个或更多个连接上,取决于我重新连接等待的时间长度,当我绑定套接字时,我会收到10048错误代码 -“地址已在使用中”。当关闭套接字时,我会执行ShutDown.Both和Close操作,以清除端口,但是当我在命令提示符中运行netstat时,我仍然发现端口处于TIME_WAIT状态。我还将套接字设置为不等待。最后,我尝试制作循环以检查端口的状态,但它以某种无限循环结束。我认为这是4分钟TIME_WAIT规则的问题。
我有一个显示nestat查询的函数,并发现当我运行该函数并检查端口是否从ESTABLISHED变为TIME_WAIT时,我可以绑定,但是当我使用此查询数据在循环中绑定时,当状态达到TIME_WAIT时,我会遇到10048错误。我的按钮单击是否允许我绑定的短暂时刻?在循环中是否存在TIME_WAIT和ESTABLISHED之间的状态,而在使用按钮单击时不存在?我读过TIME_WAIT应该完全阻止我进行绑定,但这似乎不是真的。有人能解释一下吗?
我向您代码爱好者道歉。虽然我认为这不会改变什么,但我需要更好地了解端口状态。
    public bool CheckAvailablePorts()
    {
        int temp=0;
        bool availPort= true;
        m_config = new AppConfig();
        if (!m_config.initialize())
        {
            System.Diagnostics.Debug.WriteLine("Error loading configuration file.  Exiting...");
            return false;
        }
        else
        {

//checking through all the ports that have been set to connect on

            foreach (ProxyConfig cfg in m_config.m_proxyConfigs)
            {
                availPort = true;
                temp = cfg.localEP.Port;
                DataView dv = FindEstablishedSockets();//returns netstat query
                foreach (DataRowView rowView in dv)
                {
                    DataRow row = rowView.Row;

                    if ((Convert.ToInt32(row["Local Port"].ToString()) == temp) && (row["Status"].ToString().Equals("Established")))
                    {
                        System.Diagnostics.Debug.WriteLine("Port: " + temp + " is still locked");
                        availPort = false;
                        break;
                    }
                }
            }
            return availPort;
        }
    }

//snippet out of a bigger function which checks for availability and then sleeps if false and runs again

            bool temp = false;
            while (!temp)
            {
                temp = monitor.CheckAvailablePorts();
                System.Threading.Thread.Sleep(2000);
            }
            System.Threading.Thread.Sleep(3000);
            monitor.startApplication(); //starts all the binding

在Windows上,当你释放端口后,它会保持在TIME_WAIT状态一段可配置的时间内。这个时间可以通过注册表设置:HKLM/System/CurrentControlSet/Services/Tcpip/Parameters/TCPTimedWaitDelay - Chris O
根据谁关闭连接,Time_wait 可能会发生在服务器端或客户端,也许让客户端处理这个问题? - Stephan B
http://www.isi.edu/touch/pubs/infocomm99/infocomm99-web/ 建议对TCP进行一些改变来解决这个问题。我不认为他的想法被采纳了,但是有一些关于这个问题的细节。 - Stephan B
你可能不想更改机器的全局等待时间设置,请参阅此处有关TIME_WAIT的思考:http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html - Len Holgate
3个回答

0
我读到 TIME_WAIT 应该完全阻止我绑定端口,但这似乎并不正确。
有一个选项可以让你绑定一个处于 TIME_WAIT 状态的本地端口。这非常有用,可以确保在杀死服务器后重新启动之前不必等待 4 分钟。
int flag = 1;
sockfd = socket(...);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
bind(...);

0

你需要更具体一些,因为很难知道你在做什么。提供更短的文本和代码示例会有所帮助。

我需要打开和关闭连接,然后再次重新打开它们

如果是在客户端,那应该不是问题。如果是在服务器端,请解释原因。

服务器上的配置文件正在寻找特定的端口,因此当我重新连接时,我需要再次打开相同的端口

你是什么意思?如果你指的是监听端口:你永远不应该关闭监听套接字。如果你不想接受多个套接字,只需在客户端套接字断开连接之前不再调用 Accept 即可。


你是说要关闭接受EndAccept的套接字吗? - VengefulSakhmet
相同的套接字应该调用BeginAcceptEndAccept =>监听套接字。该套接字应该在应用程序的生命周期内保持活动状态。由EndAccept返回的套接字,即客户端套接字,在连接关闭时应该被关闭。 - jgauffin
这很不寻常,但你可能有合法的理由想要关闭监听套接字,并且RFC中没有任何反驳这一点的内容。然而,这样做很棘手,需要避免进入等待状态。 - Tony Edgecombe

-2

那其实不是真的;嗯,有点混乱。请参阅http://www.serverframework.com/asynchronousevents/2011/01/time-wait-and-its-design-implications-for-protocols-and-scalable-servers.html了解详情。 - Len Holgate
这是完全不正确的说法。挂起的数据与TIME_WAIT毫无关系。当您关闭套接字时,所有挂起的数据都会被丢弃,任何后续到达的数据都会导致发出重置信号。 - user207421
哇,那是我很久以前的一篇帖子...被挖掘出来了;) 我改正了! - mBardos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接