2010-07-07 131 views
5

在TCP套接字编程中,如果recv()返回0,则表示另一方关闭其连接。但是,AFAIK,TCP RFC没有要求TCP的有效载荷大于0.因此,理论上,TCP堆栈可以接收有效载荷为0的消息。如果接收到有效负载大小为0的TCP数据包,则recv()返回什么值

所以,基本上我的问题是recv()如果返回收到大小为0的有效载荷数据包?如果它返回0,那么我们如何区分它与关闭的连接指示。

回答

11

有效载荷大小为0的TCP段无处不在 - 它们几乎出现在每个真实世界的TCP流中。只要有一方希望承认收到另一方的数据,但没有自己发送的数据,就会发送它们。 (这些通常被称为“ACK数据包”,但“ACK数据包”只是恰好不包含数据的常规段)。

由于这些包不包含任何数据,以便提供给用户的应用程序,他们不会造成recv()返回 - recv()将继续阻止,直到一些实际的数据到达。如果recv()返回0,则表明另一端已关闭其连接侧,并且不会再发送更多数据。

请记住,TCP是面向流的:有而不是调用单个recv()返回的数据与单个TCP段中的数据之间的1对1映射。一个recv()调用可能会返回一个与多个TCP段重叠的数据块,并且单个TCP段中的数据可能会在多个recv()调用中返回。使用BSD套接字API的应用程序不可见TCP段之间的边界。如果你想要这样的边界,你需要在TCP流中使用应用层协议来实现自己,或者使用像UDP这样的面向数据报的协议。

+0

+1用于提及ACK。 – 2010-07-08 10:51:12

+0

ACK数据包将设置一个ACK标志。 – AlastairG 2010-12-22 13:56:08

+1

@AlastairG:对,但是除了初始SYN或连接重置之外的每个数据包都设置了ACK位。 – caf 2010-12-22 21:36:06

3

对,根据POSIX,如果recv返回0,则该连接被对等体正确关闭。

如果有人已经成功地发送TCP数据包以零大小的有效载荷,则OS 不必返回任何数据被阻止在该插座上recv系统调用的进程。

请记住,TCP有效载荷形成一个连续的流,可能由操作系统随机分割,而不是在单个系统调用期间必须返回的数据报序列。

相关问题