在TCP套接字编程中,如果recv()
返回0,则将其视为另一方关闭其连接的指示.但是,AFAIK,TCP RFC并不要求TCP的有效载荷大于0.因此,理论上,TCP堆栈可以接收带有效载荷0的消息.
所以,基本上我的问题是,recv()
如果收到大小为0的有效负载数据包会返回什么?如果它返回0,那么我们如何将其与闭合连接指示区分开来.
有效载荷大小为0的TCP段无处不在 - 它们几乎出现在每个真实的TCP流中.只要一方希望确认从另一方收到数据,但没有自己发送的数据,就会发送它们.(这些通常称为"ACK数据包",但"ACK数据包"只是恰好不包含数据的常规段).
由于此类数据包不包含任何要传递给用户应用程序的数据,因此它们不会导致recv()
返回 - recv()
在某些实际数据到达之前将继续阻塞.如果recv()
返回0,则表明另一端已关闭其连接侧并且不再发送任何数据.
请记住,TCP是面向流的:单个调用返回的数据与单个TCP段中的数据之间没有一对一的映射关系recv()
.单个recv()
调用可能会返回与多个TCP段重叠的数据块,并且可能会在多个recv()
调用中返回单个TCP段中的数据.使用BSD套接字API,应用程序看不到TCP段之间的边界.如果您需要这样的边界,则需要使用TCP流中的应用层协议实现自己,或者使用面向数据报的协议(如UDP).