【问题标题】:How to handle socket read in C when the remote server closes socket possibly before read is finished?当远程服务器可能在读取完成之前关闭套接字时,如何处理 C 中的套接字读取?
【发布时间】:2013-07-14 02:58:23
【问题描述】:

客户端在等待读取 n 个字节的读取调用上阻塞。

服务器写入 n 个字节并立即关闭连接。

如果套接字在读取完成之前关闭或由于其他问题而在这种情况下读取调用返回负数或零吗? (在这种情况下,客户端/服务器在同一个 linux 机器上运行)

我正面临这样的情况,但不确定它在 TCP/IP 子系统中是如何工作的以及如何解决它。

Sever:
write
close

Client:
read
close

【问题讨论】:

  • Joni 下面说了什么。每个人都应该阅读 Ultimate SO_LINGER 页面 (blog.netherlabs.nl/articles/2009/01/18/…) 关于远程主机关闭套接字时丢失数据的内容。
  • 发送最后一条消息的主机应该执行半关闭:shutdown(s, SHUT_WR) 然后循环调用 recv() 一段合理的时间,直到它返回错误或 0 指示远程主机已经离开或关闭了连接。
  • 下面的答案可能会解决您的问题,但如果您需要更多帮助,请告诉我们code
  • “终极 SO_LINGER 页面”不是规范性参考。在我数十年的经验中,“它经常无法完成我们想要的事情——传输的最后千字节或有时兆字节的数据永远不会到达”的说法是完全不真实的。 '当我们在 TCP/IP 套接字上发出 close() 函数时,根据情况,内核可能会这样做:关闭套接字,并随之关闭 TCP/IP 连接。这确实发生了——即使您的一些数据仍在等待发送”是完全不正确的:它违反了 RFC 793 中的规范。
  • 不确定服务器在发送关闭后需要等待接收多长时间,因为服务器也有其他客户端并且可以工作。如果远程客户端速度很慢,不想阻塞 recv。服务器是单线程的。

标签: c sockets tcp network-programming client-server


【解决方案1】:

关闭套接字连接的安全方法是首先调用shutdown 表示您不会写入,继续读取远程端发送的数据,然后关闭读取端并关闭套接字。如果您在读取发送给您的数据之前关闭套接字,操作系统会重置连接(发送一个设置了 RST 标志的数据包)并且远程端将此解释为错误。

【讨论】:

    【解决方案2】:

    TCP 串行处理连接,阅读器按照发送者传输的顺序处理所有内容。当发送方关闭连接时,读取方将在读取所有发送的数据后收到 EOF,而不是之前。

    【讨论】:

    • 谢谢。在这种情况下我可能会得到负返回值的任何原因。客户端/服务器在同一台机器上运行,所以我不会假设套接字被破坏,因为它是一种快速查询-响应-关闭类型的应用程序。它只是偶尔发生一次,不是每次都发生。客户端工具发送命令。服务器发送回复并关闭套接字。客户端读取并关闭套接字。
    • 来自read() 的负返回表示出现错误。您应该使用perror() 来查看错误消息。
    • perror print - Connection reset by peer...我确定服务器已写入数据并关闭了套接字。客户端在选择系统调用时处于阻塞状态,超时时间为 1 秒,并试图读取数据。这怎么可能?对于相同的用例,这种情况并非每次都会发生。
    • 'Connection reset by peer'通常意味着你已经写入了一个已经被对等方关闭的连接,根据@Joni的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-30
    • 2017-06-05
    • 2014-09-24
    • 2014-03-12
    • 2011-05-07
    • 1970-01-01
    相关资源
    最近更新 更多