仅在第二次发送断开的管道时断开管道

时间:2012-09-04 13:44:53

标签: c linux sockets client

我正在通过TCP套接字测试客户端 - 服务器通信。我用C编写了服务器,我在Linux机器上运行它,我正在使用nc作为客户端进行测试。

服务器在与客户端初始交换消息后发送一些消息 消息定期发送给客户端而不会得到任何响应。

如果我杀了客户端,我希望服务器完成的第一个send()失败 EPIPE错误,但结果仅在客户端消失后的第二个send()出现! 我杀死客户端后的第一个send()能够成功发送1100个字节到(我想已关闭)套接字。以下send()操作以EPIPE结束时结束。

有人可以解释我这种行为吗? 是因为我写入TCP / IP堆栈,所以它由堆栈决定 什么时候可以提供? 如果是,我该如何检查连接状态?确保同伴还在那里。

1 个答案:

答案 0 :(得分:4)

正常TCP连接是四次握手。

http://en.wikipedia.org/wiki/Transmission_Control_Protocol

当你杀死客户端时, FIN 段从客户端发送到服务器,服务器协议栈发送 ACK

此处如果服务器尝试读取数据,则读取调用将返回值0,因此您的服务器程序可以理解对等体已关闭,并且通常会在此之后关闭连接套接字。这将允许从服务器端发送 FIN ,并在从客户端收到最后一个 ACK 后完成正常的4路握手。

(Pl阅读http://www.faqs.org/faqs/unix-faq/socket/的Q 2.1)

但是在这里您正在从服务器写入数据,因此服务器仅在发送数据后才从客户端获得 RESET 。因此,您在第二次发送时的第一次发送操作后收到错误。

所以,pl。尝试通过设置关闭来自客户端突然的连接而不是4路接听 逗留选项和超时为0,这样你就可以在服务器端的第一次发送调用中得到一个错误(可能与EPIPE不同)。(这不是一个推荐的做法,只是为了你在这个特殊情况下的理解)

Try the following option of nc, nc -L 0 to set the linger option and timeout to 0

(我没有尝试过这个nc的选项,请检查此链接中的详细信息http://docs.oracle.com/cd/E23824_01/html/821-1461/nc-1.html

来自上述网站的nc示例

Connect to TCP port, send some data and terminate the connection with 
TCP RST segment 
(instead of classic TCP closing handshake) by setting the linger option and 
timeout to 0:

$ echo "foo" | nc -L 0 host.example.com 22