我有一个多线程服务器(线程池),使用20个线程处理大量请求(一个节点最多500 /秒).有一个侦听器线程接受传入连接并将它们排队以供处理程序线程处理.一旦响应准备就绪,线程就会写出到客户端并关闭套接字.直到最近,一切似乎都很好,一个测试客户端程序在阅读响应后开始随机挂起.经过大量挖掘后,似乎服务器的close()实际上并没有断开套接字.我已经使用文件描述符编号为代码添加了一些调试打印,我得到了这种类型的输出.
Processing request for 21
Writing to 21
Closing 21
Run Code Online (Sandbox Code Playgroud)
close()的返回值为0,否则将打印另一个调试语句.在使用挂起的客户端输出此信息后,lsof将显示已建立的连接.
SERVER 8160 root 21u IPv4 32754237 TCP localhost:9980-> localhost:47530(ESTABLISHED)
客户端17747 root 12u IPv4 32754228 TCP localhost:47530-> localhost:9980(ESTABLISHED)
就像服务器永远不会将关闭序列发送到客户端一样,这种状态会一直挂起,直到客户端被终止,让服务器端处于关闭等待状态
SERVER 8160 root 21u IPv4 32754237 TCP localhost:9980-> localhost:47530(CLOSE_WAIT)
此外,如果客户端指定了超时,它将超时而不是挂起.我也可以手动运行
call close(21)
Run Code Online (Sandbox Code Playgroud)
在gdb的服务器中,客户端将断开连接.这可能发生在50,000个请求中,但可能不会在较长时间内发生.
Linux版本:2.6.21.7-2.fc8xen Centos版本:5.4(最终版)
套接字动作如下
服务器:
int client_socket; struct sockaddr_in client_addr; socklen_t client_len = sizeof(client_addr);
while(true) {
client_socket = accept(incoming_socket, (struct sockaddr *)&client_addr, &client_len);
if (client_socket == -1)
continue;
/* insert into queue here for threads to process */ …Run Code Online (Sandbox Code Playgroud) 我在工作中经历了一些代码,我发现了这一点
inline
FLAGS get_flags(void) {
FLAGS res;
memset(&res, 0, sizeof(res));
return res
}
Run Code Online (Sandbox Code Playgroud)
这是在程序中包含的头文件中声明的.我意识到,如果没有内联,因为这是在堆栈上分配的,这将是一件非常糟糕的事情.我们从未遇到过相关代码的问题,但我对此感到好奇.