尝试重新绑定已经关闭的监听套接字失败(EADDRINUSE)?

时间:2018-07-06 14:31:00

标签: c linux sockets

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

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。

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

1 个答案:

答案 0 :(得分:9)

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

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

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