Processing request for 21
Writing to 21
Closing 21
调用close()方法的返回值应为0,否则会打印另一条调试语句。在使用出现问题的客户端时,lsof工具显示建立了一个连接。
服务器端:
8160 root 21u IPv4 32754237 TCP localhost:9980->localhost:47530 (已建立连接)
客户端:
17747 root 12u IPv4 32754228 TCP localhost:47530->localhost:9980 (已建立连接)
看起来,服务器没有向客户端发送关闭序列,此状态一直挂起,直到客户端被杀死,导致服务器处于关闭等待状态。
服务器端:
8160 root 21u IPv4 32754237 TCP localhost:9980->localhost:47530 (CLOSE_WAIT状态)
如果客户端指定了超时时间,它将会超时而不是挂起。我也可以手动运行...
call close(21)
在服务器上使用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 */
}
接下来,线程将获取套接字并构建响应。
/* get client_socket from queue */
/* processing request here */
/* now set to blocking for write; was previously set to non-blocking for reading */
int flags = fcntl(client_socket, F_GETFL);
if (flags < 0)
abort();
if (fcntl(client_socket, F_SETFL, flags|O_NONBLOCK) < 0)
abort();
server_write(client_socket, response_buf, response_length);
server_close(client_socket);
server_write 和 server_close。
void server_write( int fd, char const *buf, ssize_t len ) {
printf("Writing to %d\n", fd);
while(len > 0) {
ssize_t n = write(fd, buf, len);
if(n <= 0)
return;// I don't really care what error happened, we'll just drop the connection
len -= n;
buf += n;
}
}
void server_close( int fd ) {
for(uint32_t i=0; i<10; i++) {
int n = close(fd);
if(!n) {//closed successfully
return;
}
usleep(100);
}
printf("Close failed for %d\n", fd);
}
客户端:
客户端使用的是libcurl v7.27.0
CURL *curl = curl_easy_init();
CURLcode res;
curl_easy_setopt( curl, CURLOPT_URL, url);
curl_easy_setopt( curl, CURLOPT_WRITEFUNCTION, write_callback );
curl_easy_setopt( curl, CURLOPT_WRITEDATA, write_tag );
res = curl_easy_perform(curl);
没有花哨的东西,只是一个基本的curl连接。客户端在tranfer.c(在libcurl中)挂起,因为套接字没有被认为已关闭。它正在等待来自服务器的更多数据。
到目前为止我尝试过的事情:
在关闭之前进行关闭
shutdown(fd, SHUT_WR);
char buf[64];
while(read(fd, buf, 64) > 0);
/* then close */
将SO_LINGER设置为1秒强制关闭
struct linger l;
l.l_onoff = 1;
l.l_linger = 1;
if (setsockopt(client_socket, SOL_SOCKET, SO_LINGER, &l, sizeof(l)) == -1)
abort();
这些都没有起到任何作用。如有任何想法,将不胜感激。
编辑--最终发现这是由于队列库中的线程安全问题导致多个线程不适当处理套接字。
close
关闭套接字时可能正在使用它吗?你如何进行非阻塞读取? - David Schwartz