【问题标题】:Receiving data from already closed socket?从已经关闭的套接字接收数据?
【发布时间】:2012-08-07 01:19:02
【问题描述】:

假设我有一个服务器应用程序 - 通过 TCP 连接,使用 UNIX 套接字。

连接是异步的——换句话说,客户端和服务器的套接字是非阻塞的。

假设以下情况:在某些情况下,服务器可能决定向已连接的客户端发送一些数据并立即关闭连接:使用shutdownSHUT_RDWR

所以,我的问题是 - 是否可以保证,当客户端调用 recv 时,它会收到(由服务器发送的)数据?

或者,要接收数据,必须在服务器的shutdown 之前调用recv?如果是这样,我应该怎么做(或者,更准确地说,我应该怎么做),以确保客户端接收到数据?

【问题讨论】:

    标签: c++ c sockets unix client-server


    【解决方案1】:

    无法保证您会收到任何数据,更不用说这些数据了,但是当套接字关闭时待处理的数据与所有其他数据一样受到相同的保证:如果它到达,它将到达时按顺序到达,完好无损,并受到 TCP 的最大努力。

    注意“异步”和“非阻塞”是两个不同的东西,而不是同一事物的两个术语。

    【讨论】:

      【解决方案2】:

      一旦你成功地将数据写入到套接字中,它就会在内核的缓冲区中,直到它被发送和确认为止。关机不会导致缓冲数据丢失。关闭套接字不会导致缓冲数据丢失。即使发送进程的死亡也不会导致缓冲的数据丢失。

      您可以使用netstat 观察缓冲区的大小。 SendQ 列是内核仍要传输的数据量。

      客户端确认一切后,端口从服务器上消失。这可能发生在客户端读取数据之前,在这种情况下,它将在客户端的 RecvQ 中。基本上你没有什么可担心的。在成功写入 TCP 套接字后,每个组件都会尽其所能确保您的数据不受损害地到达目的地,而不管发送套接字和/或进程发生了什么。

      好吧,也许要担心一件事:如果客户端在服务器关闭后尝试发送任何内容,它可能会在从套接字读取所有可用数据之前获得一个 SIGPIPE 并死掉。

      【讨论】:

      • 发送进程的终止会导致 Windows 上的 RST。端口在最终的 FIN 和 ACK 以及可能的 TIME-WAIT 之后从服务器上消失,而不是之前。
      【解决方案3】:

      您可以使用“setsockopt(SO_LINGER)”控制此行为:

      SO_LINGER 如果存在数据,则等待完成关闭功能。当启用此选项并且关闭时存在未发送的数据 函数被调用,调用应用程序在调用期间被阻塞 关闭函数,直到数据传输完毕或连接有 时间到。 close 函数在不阻塞调用者的情况下返回。 此选项仅对流套接字有意义。

      另见:

      【讨论】:

      • 对,答案是取决于服务器设置的套接字选项。
      • 这究竟是如何回答这个问题的?他没有问如何控制发送者的行为,他问的是接收者的行为是什么。设置延迟超时丝毫不会改变它。 (关闭它 off 确实如此,但你没有提到这一点。)
      • 我不明白。所以,我需要设置SO_LINGER,然后close函数在客户端收到数据或者超时之前不会关闭socket,对吧?如果是这样,那么“关闭函数如何在不阻塞调用者的情况下返回”?或者,也许操作系统会处理这个问题,而我的服务器不会在关闭时阻塞?另外,为@EJP 的评论 +1。
      • 此外,Beej 的指南对此也只字未提。我看过了,只是又看了一遍,没有看到关于这个案例的任何内容。
      • 这没有回答问题
      猜你喜欢
      • 2023-03-20
      • 2014-09-09
      • 2014-10-05
      • 1970-01-01
      • 2014-03-01
      • 1970-01-01
      • 2020-11-16
      • 1970-01-01
      相关资源
      最近更新 更多