为什么TCP会在接收端缓存数据

10
在TCP PUSH功能的大多数描述中,提到PUSH功能不仅要求发送方立即发送数据(而不是等待缓冲区填满),还要求将数据推送到接收方应用程序,而不会被缓冲。
我不理解的是,为什么TCP在接收端缓冲数据呢?毕竟,TCP分段以IP数据报的形式传输,在IP层处理完整个数据报之后(即IP层在对任何给定分段所携带的IP数据报片段进行重新组装后,仅将整个分段交付给TCP层),为什么接收方TCP层要等待将此数据传递给其应用程序?一种情况可能是应用程序当前没有读取数据。但是,如果是这种情况,那么强制将数据推送到应用程序也是不可能的。因此,我的问题是,为什么PUSH功能需要规定接收方行为?假设一个应用程序在分段到达时正在读取数据,那么应该立即将该分段传递给应用程序。
请问有人可以帮助解答我的疑问吗?
2个回答

8
TCP必须缓存接收到的数据,因为它不知道应用程序实际读取数据的时间,并且已经告诉发送方它愿意接收(可用的“窗口”)。所有这些数据都存储在“接收窗口”中,直到被应用程序读出。

一旦应用程序读取数据,它会从接收窗口中删除数据,并使用下一个ACK向发送方报告增加的大小。如果不存在此窗口,则发送方必须等待接收方告知其何时可以发送,而接收方无法在应用程序发出读取请求之前执行此操作。这将使每个读取调用增加一个完整的往返延迟的延迟,如果不是更多。

大多数现代实现还利用此缓冲区来保持接收到的无序数据包,以便发送方只需重传丢失的数据包,而不是其后的所有数据包。

PSH位通常没有被使用。是的,实现会发送它,但通常不会改变接收端的行为。


你为什么声称PSH位没有被使用?我已经看到它很多次了,我确信这个被广泛使用。相反,URG似乎没有被使用... - codewarrior
1
@codewarrior 它已被设置但从未被读取。TCP堆栈对于传入数据的处理方式无论PSH标志是否设置都是相同的。它最初是为某种中断编程API而设计的。在套接字API中它没有任何用途。 - user207421
谢谢Brian和EJP,你们的回答非常有启发性!我怀疑缓冲区是用来保存数据直到应用程序读取它的,但PUSH位的描述让我对此感到困惑。很有趣的是,大多数TCP实现在接收端不解释PUSH位,这与广泛记录的情况不同。 - user1510194

3
请注意,尽管其他评论是正确的(在大多数实现中,PSH位对应用程序行为的影响很小),但TCP仍然使用它来确定ACK行为。具体而言,当设置了PSH位时,接收TCP将立即发送ACK而不是使用延迟ACK。这只是一个小细节 ;)

谢谢 Neville 提供的额外信息。然而,TCP 通常何时延迟 ACK 呢? - user1510194
通常情况下,TCP 会延迟确认直到接收到两个完整大小的数据段,或者延迟 ACK 计时器到期(我相信这通常需要 ~200 毫秒)。 - NevilleS
我不记得RFC中有这个内容(虽然我承认已经有一段时间了)。你能提供一个参考吗? - Brian White

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