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

wor*_*bin 3 c sockets linux

以下是我的测试夹具的精髓 -

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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

PS - 相同的代码在Windows上正常工作,在Linux上发生bind()失败.

rit*_*lew 9

您试图解决的是TCP网络层的内置功能.Linux内核不允许您重新绑定该套接字,因为关闭的套接字将处于TIME_WAIT状态.除了使用SO_REUSEADDR(正如您已经指出的那样),或者通过为每个测试使用不同的端口,您可以做任何事情来规避它,这听起来不像您想要做的那样.

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

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