epoll服务器不会解除绑定

时间:2013-02-06 00:42:00

标签: linux epoll

我在Ubuntu Linux内核3.5.0-23上编写了一个epoll服务器,运行良好,遇到一个问题: 如果客户端连接,然后注销,我可以立即重启服务器。 但是,如果客户端仍然连接并关闭服务器,他将被断开连接,但端口仍然会被绑定X秒(不能告诉X,我会说它大概是20)。 如果我用编译器终止程序,也会发生这种情况。

关闭时,我使用了与客户离开时相同的功能:

int CEpollClient::Close ()
{
    if(m_socket!=SOCKET_ERROR)
    {
    int res=::epoll_ctl (m_server_handler, EPOLL_CTL_DEL, m_socket, 0);
    _debug_message("client exits");
    _debug_message(res);
    shutdown(m_socket,SHUT_RDWR);
    ::close (m_socket);
    m_socket=SOCKET_ERROR;
    }
    return 0;
 }

这是客户端类的一部分,所以这个完全相同的代码被调用,无论我是在他自己离开或初始化之后关闭客户端。 我在关闭服务器时也关闭了侦听套接字:

if (m_listener != SOCKET_ERROR)
{
    _debug_message("stop listener");
    code=epoll_ctl(m_epoll_handler,EPOLL_CTL_DEL,m_listener,0);
    _debug_message(code);
    shutdown(m_listener,SHUT_RDWR);
    ::close(m_listener);
    m_listener = SOCKET_ERROR;
}

有人可以提出任何想法吗?这并不可怕而且可行,但看起来确实像个bug。 调试消息中的返回码始终为0 - 没有错误。 那么为什么会这样呢?

2 个答案:

答案 0 :(得分:1)

我猜您无法重新使用套接字,因为您需要向系统请求它。在调用bind(2)之前做这样的事情:

https://github.com/edsiper/monkey/blob/master/src/mk_socket.c#L114

我希望它有所帮助。

答案 1 :(得分:1)

你质疑与epoll无关,但与套接字有关。你不能重用那个套接字的原因是它仍然在TCP TIME_WAIT状态中挥之不去。这是正常行为,按设计。延迟通常是最大段寿命的两倍,以确保在任何情况下都可以执行完整的往返以执行正确的关闭,但它也可以使用SO_LINGER进行配置。您可能很想简单地将SO_LINGER配置为更短的内容,但不要这样做。使用此拨号是不可取,因为它可能会干扰正常,正常的关机。

另一种选择是设置SO_REUSEADDR套接字选项,这可能就是你想要的。请注意SO_REUSEADDR告诉套接字层忘记它所做的正确性承诺并故意破坏正常的可操作性。基本上你是在告诉你的网络库:“是的,我知道这样做是错的,但我保证不再关心那个插座而且不会发生任何邪恶的事情”
这正是你的例子中的情况。你已经用困难的方式关闭了套接字,它已经消失了,没有其他人在使用它,而你所关心的只是尽快重新使用它。

有关可用套接字选项的说明,请参阅socket(7),例如。