在TCP套接字编程中,如果recv()
返回0,则表示另一方关闭了其连接。但是,AFAIK,TCP RFC并未强制要求TCP的有效载荷>因此,理论上,TCP堆栈可以接收带有效负载0的消息。
所以,基本上我的问题是,如果recv()
收到大小为0的有效负载数据包将会返回什么?如果它返回0,那么我们如何将其与闭合连接指示区分开来。
答案 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随机切片,而不是在单个系统调用期间必须返回的数据报序列。