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

7
假设我有一个服务器应用程序 - 连接通过TCP使用UNIX套接字。
连接是异步的 - 换句话说,客户端和服务器的套接字是非阻塞的。
假设出现以下情况:在某些条件下,服务器可能决定向已连接的客户端发送一些数据,并立即关闭连接:使用shutdown与SHUT_RDWR。
那么,我的问题是 - 是否保证当客户端调用recv时,它将接收到(由服务器发送的)数据?
或者,要接收数据,必须在服务器的shutdown之前调用recv?如果是这样,我应该怎么做(更准确地说,应该如何做),以确保客户端接收到数据?
3个回答

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

SO_LINGER 如果存在数据,则等待完成关闭功能。启用此选项并且在调用关闭函数时存在未发送的数据时,调用应用程序将在关闭函数期间被阻塞,直到数据被传输或连接超时。关闭函数返回而不阻止调用者。此选项仅适用于流套接字。

另请参见:


1
正确的答案是取决于服务器设置了哪些套接字选项。 - jxh
2
这个回答怎么准确地回应了问题?他没有问如何控制发送者的行为,而是问接收者的行为是什么。设置Linger超时根本不会改变这一点。(将其关闭会有影响,但你没有提到。) - user207421
1
我不明白。所以,我需要设置SO_LINGER,那么关闭函数在客户端接收数据或超时发生之前不会关闭套接字,对吗?如果是这样的话,那么“关闭函数返回而不阻塞调用者”如何实现?或者,也许操作系统会处理这个问题,我的服务器将不会在关闭时被阻塞吗?同时,点赞@EJP的评论。 - Kiril Kirov
1
此外,Beej的指南没有提到这一点。我已经阅读过它,我刚刚又看了一遍,但是我没有看到关于这种情况的任何内容。 - Kiril Kirov
2
这个回答并没有解答问题。 - Sam
显示剩余2条评论

5

不能保证您会收到任何数据,更不用说这些数据了,但是当套接字关闭时待处理的数据与所有其他数据一样受到保护,如果到达,则按顺序到达,并且未受损并受TCP最大努力的保护。

NB “异步”和“非阻塞”是两个不同的概念,而不是相同概念的两个术语。


4
一旦您成功地将数据写入套接字中,它就在内核的缓冲区中,直到发送和确认为止。关闭连接或套接字不会导致缓冲数据丢失,即使发送进程死亡也不会丢失缓冲数据。
您可以使用netstat观察缓冲区的大小。SendQ列是内核仍然要传输的数据量。
客户端确认所有数据后,端口从服务器中消失。这可能会在客户端读取数据之前发生,在这种情况下,数据将在客户端的RecvQ中。基本上,您无需担心。成功向TCP套接字写入数据后,每个组件都尽最大努力确保您的数据无论发送套接字和/或进程发生什么都能安全到达目标。
嗯,也许有一件事需要担心:如果客户端在服务器完成其关闭操作后尝试发送任何内容,它可能会收到SIGPIPE信号并在读取套接字中的所有可用数据之前死亡。

1
发送进程的终止会在Windows上引起RST。端口会在最终的FIN和ACK以及可能的TIME-WAIT之后消失,而不是在此之前从服务器上消失。 - user207421

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接