如果recv()收到有效负载大小为0的有效TCP数据包,则返回什么值

时间:2010-07-07 19:16:29

标签: tcp recv

在TCP套接字编程中,如果recv()返回0,则表示另一方关闭了其连接。但是,AFAIK,TCP RFC并未强制要求TCP的有效载荷>因此,理论上,TCP堆栈可以接收带有效负载0的消息。

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

2 个答案:

答案 0 :(得分:11)

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

由于此类数据包不包含要传递给用户应用程序的任何数据,因此它们不会导致recv()返回 - recv()将继续阻塞,直到某些实际数据到达为止。如果recv()返回0,则表明另一端已关闭其连接端并且不再发送任何数据。

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

答案 1 :(得分:3)

是的,根据POSIX,如果recv返回0,则对等方正确关闭连接。

如果某人设法发送了一个零大小的有效负载的TCP数据包,则操作系统不必将任何数据返回到recv系统调用中被阻止的进程在那个插座上。

请记住,TCP有效负载形成一个连续的流,可以由OS随机切片,而不是在单个系统调用期间必须返回的数据报序列。