【问题标题】:Port Stuck in Time_Wait端口卡在 Time_Wait
【发布时间】:2011-08-01 12:09:56
【问题描述】:

我在 C# 中有一个 TCP 隧道。我需要打开和关闭隧道,这是我在服务器和客户端之间的应用程序。我正在使用它来关闭数据连接以测试另一个应用程序。我必须使用特定的端口。

在第二个、第三个、第 n 个连接上,取决于我等待重新连接的时间,我在绑定我的套接字时收到一个 10048 错误代码 - “地址已在使用中”。关闭套接字时,我确实执行了 ShutDown.Both 和 Close 以希望清除端口,但是当我在命令提示符下执行 netstat 时,我仍然发现端口保存在 TIME_WAIT 中。我还将套接字设置为不逗留。最后,我尝试创建一个循环来检查端口的状态,但它以一个无限循环结束。我认为这是 4 分钟 TIME_WAIT 规则。

我有一个函数来显示一个嵌套查询,我发现当我运行它并检查直到端口从 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
  • 取决于谁关闭Connection,Time_wait可能发生在服务器端或客户端,也许让客户端关心这个?
  • isi.edu/touch/pubs/infocomm99/infocomm99-web 建议对 TCP 进行一些更改以解决此问题。我认为他的想法没有成功,但有一些关于这个问题的细节。
  • 您可能不想更改机器范围的时间等待设置,请参阅此处了解我对 TIME_WAIT 的看法:serverframework.com/asynchronousevents/2011/01/…

标签: c# tcp ports netstat time-wait


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 你是说杀死接受 EndAccept 的套接字吗?
  • 同一个socket应该调用BeginAcceptEndAccept =>监听socket。该套接字应该在应用程序生命周期内存在。 EndAccept返回的socket,客户端socket,应该在连接关闭的时候关闭。
  • 这很不寻常,但您可能有正当理由想要关闭侦听套接字,并且 RFC 中没有任何内容反驳这一点。然而,不进入等待状态是很棘手的。
【解决方案2】:

我读到 TIME_WAIT 应该完全阻止我绑定,但这似乎不是真的。

您可以使用一个选项来绑定处于 TIME_WAIT 中的本地端口。这对于确保您在杀死服务器后无需等待 4 分钟即可重新启动它非常有用。

int flag = 1;
sockfd = socket(...);
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag));
bind(...);

【讨论】:

    【解决方案3】:

    在关闭一个套接字之前,你必须读取其对端发送的所有数据,否则它将停留在 TIME_WAIT 以确保新的套接字不会读取前一个(关闭的)的数据。你也可以试试socket的no lingering选项。

    详情:http://msdn.microsoft.com/en-us/library/windows/desktop/ms738547%28v=vs.85%29.aspx

    【讨论】:

    • 这实际上不是真的;好吧,它很混乱。详情请见serverframework.com/asynchronousevents/2011/01/…
    • 完全不真实。待处理的数据与 TIME_WAIT 无关。当您关闭套接字时,它全部被丢弃,并且任何进一步到达的数据都会导致发出重置。
    • 哇,那是我的一篇很老的帖子……复活了;)我站得更正了!
    猜你喜欢
    • 1970-01-01
    • 2016-12-22
    • 2015-05-16
    • 2020-07-26
    • 2010-09-23
    • 1970-01-01
    • 2020-05-17
    • 2015-11-22
    • 1970-01-01
    相关资源
    最近更新 更多