情况如下:我有2台机器,A和B. A监听端口p。 B创建一个套接字s1并连接到p。 A接受套接字s2中的连接。目前,A和B可以通过套接字相互通信。
但是,如果我在A中终止该程序,然后在一段时间后重启该程序,B不知道,因为在此期间它没有向A发送任何数据。现在B开始通过s1向A写入数据。接下来会发生什么?为什么呢?
实际上我发现write
调用没有失败,但A仍然没有得到数据。更重要的是,如果我将s1放入epoll设备,我发现epoll_wait
返回EPOLLERR | EPOLLHUP
之后返回的事件为write
。为什么呢?
不幸的是,在这种情况下,它似乎丢失了数据,因为`write'调用没有失败,但A无法获取数据。任何解决方案?
答案 0 :(得分:2)
当您杀死已建立套接字的程序时,它会将RST发送到所有其他端。因此B应该在s1上接收RST,并且s1上的所有未来调用都将返回错误。但是有些防火墙可能会过滤掉RST数据包,你可以用tcpdump检查RST数据包。
如果B在步骤1中没有收到RST数据包,当它继续向A发送其他数据包(写入)时,A将使用RST数据包进行回复,并且一旦B接收到该数据,B上的所有将来呼叫都将返回错误RST。
如果B在步骤2中也没有收到RST数据包,经过一段时间(写入超时)后,B将断开连接,以后B上的所有呼叫都将返回错误。
你可以看到,写入调用很少返回错误,如果数据包发送则返回成功,不关心远程端是否收到数据包。
在你的情况下,你在调用epoll_wait时没有得到EPOLLHUP,但是在收到RST或写入超时之后
答案 1 :(得分:2)
如果套接字的另一端已经关闭,它实际上是可读的,read
(或recv
)调用将返回零,表示另一端的套接字已正常关闭
答案 2 :(得分:1)
您写入了断开连接的流(即使您的计算机不知道它已断开连接。由于您说“接受连接”,我假设您在两台计算机之间设置了TCP连接。)
如果您正在谈论UDP,则没有侦听/连接/接受,并且数据将被发送到在addr / port处侦听的任何内容。但你不是在谈论UDP。 [编辑说明结论:]你正在将数据写入一个死连接(在某些时候,很明显连接已经死了,现在你已经尝试使用它了)。写入数据不会告诉您对方是否收到了数据,成功告诉您已将数据排队等待发送。