首页 > 解决方案 > 尝试重新绑定已经关闭的侦听套接字失败(EADDRINUSE)?

问题描述

以下是我的测试夹具的本质 -

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 == 98EADDRINUSE 的 bind() 调用时失败。

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

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

标签: clinuxsockets

解决方案


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

不幸的是,TCP 的设计不是为了连续多次关闭和打开同一个 IP/端口进行测试,所以如果你仍然想进行这种测试,你将不得不选择你的毒药。

另请参阅此答案以更深入地探索您的问题。


推荐阅读