0

更新:在调查 lil 之后,我发现了这种行为的真正问题。问题是,我正在为每个连接创建线程并将 sock fd 传递给线程,但没有立即 pthraed_joining,这样我的主线程就无法在连接接受后创建更多线程。我关闭套接字的逻辑是在子线程中,因为我无法关闭套接字,因此他们将进入等待关闭状态。所以我只是在创建线程后将它们分离,现在一切正常!

我有一个客户端服务器程序,我正在使用脚本来运行客户端并建立尽可能多的连接并在发送一行数据并退出客户端后关闭它们,一切正常,直到第 32739 个连接,即连接关闭双方和所有人,但在那个数字之后,连接没有关闭,服务器停止接收更多连接,如果这样做

netstat -tonpa 2>&1 | grep CLOSE

我看到大约 1020 个套接字等待关闭。从命令中采样,

tcp 25 0 192.168.0.175:16099 192.168.0.175:41704 CLOSE_WAIT 5250/./bl_manager off (0.00/0/0)
tcp 24 0 192.168.0.175:16099 192.168.0.175:41585 CLOSE_WAIT 5250/./bl_manager off (0.00/0/0)
tcp 30 0 192.168.0.175:16099 192.168.0.175:41679 CLOSE_WAIT 5250/./bl_manager off (0.00/0/0)
tcp 31 0 192.168.0.175:16099 192.168.0.175:41339 CLOSE_WAIT 5250/./bl_manager off (0.00/0/0)
tcp 25 0 192.168.0.175:16099 192.168.0.175:41760 CLOSE_WAIT 5250/./bl_manager off (0.00/0/0)

我正在使用以下代码来检测客户端断开连接。

for(fd = 0; fd <= fd_max; fd++) {
    if(FD_ISSET(fd, &testfds)) {
       if (fd == client_fd) {
           ioctl(fd, FIONREAD, &nread);
           if(nread == 0) {
               FD_CLR(fd, &readfds);
               close(fd);
               return 0;
           }
       }
    }
} /* for()*/

如果我做错了什么,请告诉我。它是一个 Python 客户端和 CPP 服务器设置。

谢谢你

4

2 回答 2

2

CLOSE-WAIT 表示端口正在等待本地应用程序关闭套接字,已经收到对等方的关闭。显然,您以某种方式泄漏了套接字,可能是在错误路径中。

您“检测客户端断开连接”的代码完全不正确。您所测试的只是可以在没有阻塞的情况下读取的数据量,即已经到达的数据量。正确的测试是recv()的返回值为零或读取或写入时出现 EAGAIN/EWOULDBLOCK 以外的错误。

于 2013-07-12T23:58:29.740 回答
1

在不知道您的平台的情况下,我无法确定,但是您显然在使用select,并且距离 32768 仅几十个问题,这似乎很可能是您的问题。

Anfd_set是位的集合,由文件描述符编号索引。每个平台都有不同的最大数量。OpenBSD 和最新版本的 FreeBSD 和 OS X 通常将 fd_set 限制为FD_SETSIZE默认值 1024。不同的 linux 机器似乎有 1024、4096、32768 和 65536。

FD_ISSET(32800, &testfds)那么,如果你FD_SETSIZE是 32768 会发生什么?您要求它从任意内存中读取一些内容。

当您为参数传递 32800 时,在此之前的一个select或其他调用应该nfds会给您一个 EINVAL 错误……但从历史上看,许多平台都没有这样做。或者他们返回了一个错误,但只有在FD_SETSIZE正确填写了第一个位并将其余部分设置为未初始化的内存之后,这意味着如果您忘记检查错误,您的代码似乎可以工作,直到您强调它。

这是使用select超过几百个套接字是一个坏主意的原因之一。另一个原因是线性的(更糟糕的是,当前select套接字的数量不是线性的,而是最高 fd 的线性,所以即使在大多数客户端离开后它仍然很慢)。

大多数现代平台select也有poll,这避免了这个问题。

除非您使用的是 Windows……在这种情况下,不使用的原因完全不同select,答案也不同。

于 2013-07-12T23:58:52.167 回答