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

时间:2013-03-14 09:59:46

标签: c sockets tcp sigpipe

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

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

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

修改 有时候下面的write()也会有一个正的回报值,好像一切顺利。

3 个答案:

答案 0 :(得分:5)

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

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

答案 1 :(得分:3)

这与TCP / IP的工作方式有关,可以粗略地描述为两个主要是独立的半连接。当您关闭服务器上的套接字时,会告知客户端它不会从C<-S半连接接收更多数据,立即唤醒read(),但不会关注C->S方向。只有在尝试发送一些数据后才会重置连接。我建议TCP/IP Guide了解更多详情。

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

答案 2 :(得分:0)

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

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