在对等端关闭的TCP套接字上写入

我有一个客户端 – 服务器应用程序,其中每一方通过TCP套接字与另一方通信。

我正确建立连接,然后在客户端在套接字上写入任何数据之前崩溃服务器。
我看到的是第一次write()尝试(客户端)成功并返回实际的写入字节数,而后面的返回(如我所料) -1 (接收SIGPIPE )和errno=EPIPE

为什么第一个write()即使套接字已经关闭也是成功的?

编辑有时候下面的write()也有一个正的返回值,好像一切顺利。

你对write()的返回值意味着什么感到困惑。 这并不意味着,“同行得到了数据并承认了它”。 相反,它意味着,“我缓冲了太多的字节发送给同行,他们现在是我的责任,所以你可以忘记它们(我没有任何未决的错误)”。

也就是说,如果TCP堆栈接受写入并返回n个字节,这并不意味着它们已经被写入,只是排队等待写入。 在堆栈放弃并向您返回错误之前,它需要一些时间,也就是它开始发送网络流量后30秒。 在此期间,您可以完成多次write()调用,这些调用成功排队数据以进行发送。 (如果对等体消失,则写入错误将在c.30s中返回,或者如果可以联系对等体并立即发送RST数据包以指示连接已死亡,则会立即返回写入错误。)

这与TCP / IP的工作方式有关,可以粗略地描述为两个大多数独立的半连接。 当您关闭服务器上的套接字时,客户端被告知它不会从C<-S半连接接收更多数据,立即唤醒read() ,而不是C->S方向。 只有在尝试发送一些数据后才会重置连接。 我推荐TCP / IP指南以获取更多详细信息。

有时你可以write()两次的原因是你写的速度比往返时间快,并且可以在回复第一个之前挤压第二个write()

我正在使用以下方法来检测断开连接的服务器条件:

在套接字上获得select()超时后(虽然应该没有收到),’system(“ping -c 1 -w 1 server”);’ 命令已激活。 如果服务器已启动并且只是滞后,则ping命令将在不到0.1秒的时间内返回。 否则(服务器关闭),ping命令将在1秒后返回。