【问题标题】:Broken pipe only at the second send on a closed socket仅在关闭的套接字上的第二次发送时管道损坏
【发布时间】:2012-08-29 04:37:36
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: c linux sockets client


    【解决方案1】:

    正常的 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 次握手,这样您就可以在第一次调用时收到错误(可能与 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
    

    【讨论】:

    • 感谢您的回答,详细而清晰。不幸的是,我无法测试您建议的 nc 选项,因为我的 Linux 机器上的命令似乎不支持它。顺便说一句,您指向我的文档和您给我的解释清楚且有用。谢谢!
    猜你喜欢
    • 2022-01-10
    • 2010-12-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 1970-01-01
    相关资源
    最近更新 更多