客户端:
socket(), connect() and then
for (1 to 1024) {
write(1024 bytes)
}
exit(0);服务器:
socket(), bind(), listen()
while (1) {
accept()
while((n = read()) {
if (n == -1) abort(); /* never happended */
total_read += n
}
close()
}现在,客户端运行在NAT下的Mac上,服务器运行在我的VPS (国外)上
一般来说,它工作得很好(客户端发送所有数据,然后退出&服务器接收所有数据)
然而,当客户端正在运行,但突然网络中断了几分钟(然后又恢复)时,客户端在很长很长时间后不会退出……我用more +C终止它,然后再次运行它,服务器似乎不再读取数据(客户端仍在运行)
以下是netstat显示的内容:
客户端:
tcp4 0 130312 192.168.1.254.58573 A.B.C.D.8888 ESTABLISHED服务器:
tcp 0 0 A.B.C.D:8888 a.b.c.d:54566 ESTABLISHED 10970/a.out
tcp 102136 0 A.B.C.D:8888 a.b.c.d:60916 ESTABLISHED - A.B.C.D是我的VPS地址。a.b.c.d是我的公共客户端地址
我的问题是:
1,为什么?
2、服务器重启后工作正常,如何编写代码摆脱重启?
发布于 2014-01-23 15:31:53
在TCP中,除非您尝试在连接上发送某些内容,否则无法判断连接已失败。TCP不对连接执行主动监控(实际上,有可选的"keepalive“数据包,但这些数据包通常在连接空闲几个小时后才会发送)。当你发送一些东西时,如果等待另一台机器返回确认超时,你最终会得到一个错误。但是,如果您只是读取数据而不发送数据,则无法断定连接已失败--只是看起来发送方没有要发送的内容。
您可以通过将应用程序设计为要求客户端每N秒发送一次内容来解决此问题。然后在服务器中设置一个计时器,该计时器会检测到您已经超过N秒没有收到任何东西(您应该增加一点额外的时间,以考虑到短暂的延迟)。
发布于 2014-01-24 05:06:42
当网络中断时,发生的情况是您的客户端不断发送数据,并且在某个时候套接字发送缓冲区变满(我从您显示的内容中了解到,您正在发送1024个字节,1024次,总共1MB )。发送缓冲区的默认值可以是16KB (肯定小于1MB)。然后,当客户端尝试写入时,它将永远被阻塞。
顺便说一句,现在我在回答你的问题,我不知道在TCP超时之后,TCP是否最终放弃并关闭套接字,使套接字接口返回错误。我认为这不会发生... :) -因此,如果网络中存在问题,连接将失败,但写入和读取不会失败。
在服务器端,服务器在读取时被阻塞,因为它从未接收到EOF。
解决方案:
在客户端使用非阻塞套接字时,如果网络中断,write将返回错误EWOULDBLOCK。然后你就会意识到由于某种原因发送缓冲区已经满了。此时,您可以单击该连接,然后再次尝试连接。如果网络断开,您将收到一个错误。
在服务器端,也可以使用非阻塞套接字和带有超时的select()函数。在几次超时之后,您可能会确定新连接存在问题,并将其关闭。
https://stackoverflow.com/questions/21301854
复制相似问题