我正在使用循环从一个C Berkeley套接字中读取消息,但是我无法检测到套接字何时被断开,因此我想要接受一个新的连接。请帮忙。
while(true) {
bzero(buffer,256);
n = read(newsockfd,buffer,255);
printf("%s\n",buffer);
}
我正在使用循环从一个C Berkeley套接字中读取消息,但是我无法检测到套接字何时被断开,因此我想要接受一个新的连接。请帮忙。
while(true) {
bzero(buffer,256);
n = read(newsockfd,buffer,255);
printf("%s\n",buffer);
}
您能检测到套接字是否连接成功的唯一方式是向其写入数据。
在read()/recv()
时出现错误将指示连接已中断,但在读取时没有出现错误并不意味着连接已建立。
您可能会对阅读此内容感兴趣: http://lkml.indiana.edu/hypermail/linux/kernel/0106.1/1154.html
此外,使用TCP保持活动状态可以帮助区分非活动和断开的连接(即使应用程序没有要发送的数据,也会定期发送一些内容)。
(编辑:根据@Damon的指出,删除了错误的句子,谢谢。)
read()
返回的结果。在read()
之后,你的代码至少应该像这样:if (n == 0) // peer disconnected
break;
else if (n == -1) // error
{
perror("read");
break;
}
else // received 'n' bytes
{
printf("%.*s", n, buffer);
}
接受新连接应该在单独的线程中完成,而不是依赖于此连接的流结束。
bzero()
调用是无意义的,只是以前错误的解决方法。
这是因为您没有使用keepalive超时。 在接收方,keepalive套接字选项是检测死连接的最佳解决方案。
但是,如果您的应用程序继续向套接字写入,则需要考虑更多问题。 即使您已将keepalive选项设置为应用程序套接字,在应用程序保持在套接字上写入的情况下,您无法及时检测套接字的死连接状态。 这是由于内核tcp堆栈的tcp重传机制造成的。 tcp_retries1和tcp_retries2是用于配置tcp重传超时的内核参数。 很难预测确切的重传超时时间,因为它是通过RTT机制计算的。 您可以在rfc793中看到此计算。(3.7. 数据通信)
https://www.rfc-editor.org/rfc/rfc793.txt
每个平台都有用于TCP重传的内核配置。
Linux : tcp_retries1, tcp_retries2 : (exist in /proc/sys/net/ipv4)
http://linux.die.net/man/7/tcp
HPUX : tcp_ip_notify_interval, tcp_ip_abort_interval
http://www.hpuxtips.es/?q=node/53
AIX : rto_low, rto_high, rto_length, rto_limit
http://www-903.ibm.com/kr/event/download/200804_324_swma/socket.pdf
如果您想要尽早检测到死连接,那么应该将tcp_retries2(默认为15)的值设置得更低,但正如我已经说过的那样,这不是精确的时间。
此外,目前您无法仅为单个套接字设置这些值。它们是全局内核参数。
曾经有一些尝试将tcp重传套接字选项应用于单个套接字(http://patchwork.ozlabs.org/patch/55236/),但我认为它没有被应用到内核主线中。我在系统头文件中找不到这些选项的定义。
作为参考,您可以通过'netstat --timers'来监视您的keepalive套接字选项,如下所示。 https://stackoverflow.com/questions/34914278
netstat -c --timer | grep "192.0.0.1:43245 192.0.68.1:49742"
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (1.92/0/0)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (0.71/0/0)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (9.46/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (8.30/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (7.14/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (5.98/0/1)
tcp 0 0 192.0.0.1:43245 192.0.68.1:49742 ESTABLISHED keepalive (4.82/0/1)
reD()
返回的结果。 - user207421