从已关闭的套接字接收数据

Receiving data from already closed socket?

本文关键字:数据 套接字      更新时间:2023-10-16

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

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

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

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

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

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

  • Man setsockopt

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

另请参阅:

  • 人读

  • Beej的网络编程指南

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

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

成功将数据写入套接字后,它将在内核的缓冲区中,它将保留在那里,直到发送并确认为止。关机不会导致缓冲数据丢失。关闭套接字不会导致缓冲数据丢失。即使发送进程的死亡也不会导致缓冲数据丢失。

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

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

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