1

情况如下:我有两台机器,A 和 B。A 监听一个端口 p。B 创建一个套接字 s1 并连接到 p。A 接受套接字 s2 中的连接。目前,A 和 B 可以通过套接字相互通信。

但是,如果我杀死 A 中的程序,然后在一段时间后重新启动该程序,B 不知道,因为在此期间它没有向 A 发送任何数据。现在 B 开始通过 s1 向 A 写入数据。接下来会发生什么?为什么?

实际上我发现write呼叫没有失败,但A仍然没有得到数据。更重要的是,如果我把 s1 放在 epoll 设备中,我发现返回的事件epoll_waitEPOLLERR | EPOLLHUP在调用write. 为什么?

不幸的是,在这种情况下,它似乎丢失了数据,因为“写”调用没有失败,但 A 无法获取数据。有什么解决办法吗?

4

3 回答 3

2
  1. 当您杀死已建立套接字的程序时,它将向所有另一端发送 RST。所以 B 应该在 s1 上收到 RST,并且以后对 s1 的所有调用都将返回错误。但是有些防火墙可能会过滤掉RST包,你可以用tcpdump查看RST包。

  2. 如果 B 在步骤 1 中没有收到 RST 数据包,当它继续向 A 发送其他数据包(写入)时,A 将回复 RST 数据包,并且一旦 B 收到此 RST,以后对 B 的所有调用都将返回错误。

  3. 如果 B 在 step2 也没有收到 RST 数据包,在一定时间后(写超时),B 将断开连接,并且以后对 B 的所有调用都将返回错误。

可以看到,write调用很少返回错误,如果发送了数据包就返回成功,不关心远端是否收到数据包。

在您的情况下,您不会在调用 epoll_wait 后立即获得 EPOLLHUP,而是在收到 RST 或写入超时后

于 2012-08-20T05:29:32.380 回答
2

如果套接字的另一端已关闭,它实际上是可读的,并且read(或recv)调用将返回零,表示另一端的套接字已正常关闭。

于 2012-08-20T05:48:14.043 回答
1

您写入了断开连接的流(即使您的机器不知道它已断开连接。既然您说“接受连接”,我假设您正在两台机器之间建立 TCP 连接。)

如果您在谈论 UDP,则没有 Listen/Connect/Accept,并且数据将被发送到在 addr/port 上侦听的任何内容。但你不是在谈论UDP。[编辑以阐明结论:]您正在将数据写入死连接(并且在某些时候很明显连接已死,现在您已尝试使用它)。写入数据不会告诉你对方是否收到数据,成功告诉你它已经将要发送的数据排队。

于 2012-08-20T05:20:31.417 回答