【问题标题】:Attempt to re-bind an already closed listening socket is failing (EADDRINUSE)?尝试重新绑定已经关闭的侦听套接字失败(EADDRINUSE)?
【发布时间】:2018-12-15 04:41:17
【问题描述】:

以下是我的测试治具的精华-

SetUp()
{
    g_listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    /* localhost is the server */
    bind(g_listen_sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
    listen(g_listen_sock, max_connections);
}

testcase()
{
    hdl = accept(g_listen_sock, NULL, NULL);
    -- send()/recv() data on the socket --
}

TearDown()
{
    shutdown(g_listen_sock, SHUT_RDWR);
    close(g_listen_sock);
    g_listen_sock = INVALID_SOCKET;
}

在应用程序的正常使用中,监听套接字在应用程序的生命周期内只绑定一次,但是测试设置会反复打开和关闭监听套接字。测试用例的第一次迭代工作正常,但随后的迭代在使用errno == 98 即 EADDRINUSE 的 bind() 调用中失败。

如何避免这种情况? 理想情况下,该解决方案不需要我拥有单独的代码测试版本,例如在测试时使用 SO_REUSEADDR。

附: - 相同的代码在 Windows 上运行良好,bind() 失败发生在 Linux 上。

【问题讨论】:

标签: c linux sockets


【解决方案1】:

您要解决的是网络 TCP 层的内置功能。 linux 内核不允许您重新绑定该套接字,因为关闭的套接字将处于 TIME_WAIT 状态。除了使用SO_REUSEADDR(正如您已经指出的那样)或为每个测试使用不同的端口(听起来您也不想这样做)之外,您无能为力。

不幸的是,TCP 并非设计为连续多次关闭和打开同一个 IP/端口进行测试,因此如果您仍想进行此类测试,则必须选择毒药。

另请参阅this answer 以更深入地探索您的问题。

【讨论】:

  • 为什么在Windows中重复重新打开会有所不同?
  • 老实说,我不确定为什么会发生这种情况。当我在 Windows 上进行套接字编程时,我通常会遇到与您相同的问题。就目前而言,Windows 和 Linux 是不同的操作系统,问题出在操作系统级别(可以这么说)。所以这只是操作系统之间TCP实现不同的结果。
  • 在 Windows 注册表中更改 TIME_WAIT 延迟相当简单。但是,最好在专用测试盒上进行,因为它是机器范围的设置。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-20
  • 1970-01-01
  • 1970-01-01
  • 2013-12-02
相关资源
最近更新 更多