套接字在进程后打开,打开它就完成了

时间:2015-08-05 11:21:50

标签: c++ c sockets log4cxx apr

在服务器端关闭客户端套接字并退出应用程序后,套接字仍然打开一段时间。

我可以通过netstat

看到它
void Socket::close() {
    if (socket != 0) {
        apr_status_t shutdown_status = apr_socket_shutdown(socket, APR_SHUTDOWN_READWRITE);
        printf("Socket::close shutdown_status %d\n", shutdown_status);
        if (shutdown_status != APR_SUCCESS) {
            printf("Socket::close WTF %d\n", shutdown_status != APR_SUCCESS);
            throw SocketException(shutdown_status);
        }
        apr_status_t close_status = apr_socket_close(socket);
        printf("Socket::close close_status %d\n", close_status);
        if (close_status != APR_SUCCESS) {
            printf("Socket::close WTF %d\n", close_status != APR_SUCCESS);
            throw SocketException(close_status);
        }
        socket = 0;
    }
}

我使用log4cxx日志记录和telnet appender。 log4cxx使用apr套接字。 Socket :: close()方法看起来像这样:

dump

它已成功处理。但是程序完成后我可以通过netstat看到打开的socket,如果再次启动,log4cxx无法打开6676端口,因为它很忙。 我试图修改log4cxx。 关闭前关闭套接字:

>>> d1 = dict(zip(range(10),range(10)))
>>> d2 = dict(zip(range(10,20),range(10,20)))
>>> d3 = dict(zip(range(20,30),range(20,30)))
>>> d4 = dict(zip(range(30,40),range(30,40)))
>>> x = [d1,d2,d3,d4]
>>> fnames = ['a.pik', 'b.pik', 'c.pik', 'd.pik']
>>> 
>>> import pathos
>>> p = pathos.pools.ProcessPool()
>>> 
>>> def dump(data, fname):
...   import dill
...   with open(fname, 'w') as f:
...     dill.dump(data, f)
...   return
... 
>>> r = p.uimap(dump, x, fnames)
>>> # no need to do this, but just FYI, it returns nothing
>>> list(r)
[None, None, None, None]
>>> 

但它没有帮助,bug仍在复制。

3 个答案:

答案 0 :(得分:2)

这不是错误。时间等待(和关闭等待)是出于安全目的而设计的。但是,您可以调整等待时间。在任何情况下,从服务器的角度来看,套接字是关闭的,你可以通过ulimit计数器放松,除非你正在进行压力测试,否则它没有太大的明显影响。

答案 1 :(得分:2)

正如凯文所说,这不是一个错误,它是一个功能。 Time Wait是一个套接字状态,表示此套接字不再使用,但仍然无法重用。

想象一下,您打开了一个套接字并且某个客户端正在发送数据。当服务器关闭其套接字时,数据可以在网络中备份或在飞行中。

现在假设您再次启动服务或启动一些新服务。线路上的数据包不知道它的新服务和服务无法知道数据包的目的地是已经消失的服务。新服务可能会尝试解析数据包并失败,因为它们处于某种奇怪的格式或客户端可能会收到无关的错误并继续尝试发送,可能是因为序列号不匹配而接收主机会得到一些奇怪的错误。通过定时等待,客户端将收到通知,即套接字已关闭,服务器可能无法获取奇数数据。双赢。它等待的时间应该是所有在途数据从系统中消失的缺点。

请查看此帖子以获取更多信息:Socket options SO_REUSEADDR and SO_REUSEPORT, how do they differ? Do they mean the same across all major operating systems?

答案 2 :(得分:0)

TIME_WAIT是一种套接字状态,允许所有 in travel 数据包可以从连接中保留到连接参数之前到达或死亡(源地址,源端口,desintation地址,目标) port)可以再次使用。在允许您再次重用该套接字之前,内核只是设置一个等待这个时间的计时器。但你不能缩短它(即使你可以,你最好不要这样做),因为你不可能知道是否仍然有数据包在旅行或加速或杀死它们。您唯一的可能性是等待绑定到该端口的套接字超时并从状态TIME_WAIT传递到CLOSED状态。

如果你被允许重用连接(我认为有一个选项或者可以在linux内核中完成)并且你收到一个旧的连接数据包,你可以通过收到的数据包获得连接重置。这可能会导致新连接出现更多问题。解决了这些问题,等待所有属于旧连接的流量在再次使用该套接字之前死亡或到达目的地。