7

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

服务器在与客户端进行初始消息交换后,会定期向客户端发送一些消息而没有得到任何响应。

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

有人可以向我解释这种行为吗?是不是因为我写入 TCP/IP 堆栈,所以它可以由堆栈来交付?如果是这样,我如何检查连接状态?确保对等体仍然存在。

4

1 回答 1

4

正常 TCP 连接是四次握手。

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

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

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

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

但是这里你是从服务器写入数据,所以服务器只有在发送数据后才会从客户端获得一个RESET 。因此,在第二次发送的第一次发送操作之后,您会收到错误消息。

所以,请。通过将 linger 选项和超时设置为 0,尝试从客户端突然关闭连接,而不是 4 次握手,这样您就可以在服务器端第一次调用 send 时收到错误(可能与 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
于 2012-09-04T15:15:02.620 回答