PSH是一种通过TCP发送数据的方式。除此之外,我找不到关于如何正确实施它的信息。
这是我感兴趣的:
假设服务器窗口是8000字节,我发送了2个150和600字节的请求。我是否会得到某种数据已收到的确认信息?我可以以某种方式触发确认吗?
我见过一些ACK数据包,它们不包含PSH,但包含某种有效负载数据(Wireshark将其标记为“TCP段数据”)。这些数据是否传递给用户,如果是,为什么我们需要 PSH 标志?
TCP PSH 通常根本不起作用。 Berkely 派生的 TCP 实现完全忽略它。
来源:W.R. Stevens,TCP/IP 图解,第一卷:20.5 PUSH Flag。
@Arsen:回答你问题的第二部分“为什么我们需要 PSH 标志?” TCP 标头中的 PSH 标志通知接收主机应立即将数据推送到接收应用程序。 我们正在使用 PSH 标志在两个服务器之间交换时间戳值。
我假设,如果我们设置推送标志,数据包将不会在接收缓冲区中等待,它将直接发送到接收者。
根据我在 Linux 中的观察,发送方 TCP 堆栈将设置 PUSH=0 作为立即跟随更多字节的提示。
例如,当发送方使用大于 MSS(最大段大小,通常为 1460 字节)的数据缓冲区调用
send()
时,就会发生这种情况。
在接收端,启用 LRO(大型接收卸载)的网络适配器可以在看到 PUSH=0 时稍微等待下一个 TCP 段,当它到达时,将两个 TCP 段合并为一个更大的段。这种合并发生在网卡本身,没有 CPU 的参与。合并后,CPU 仅被中断一次并仅传递一个内存缓冲区描述符,从而减少总内存占用并减少处理量,因为您只有 1 个标头和 1 个中断(而不是 2 个)。
即使网络驱动程序在轮询模式而不是中断模式下运行,(吞吐量)性能优势仍然存在。
Wireshark 显示 TCP 段大于 MSS 表明 LRO 已启用。
原则上,接收网络适配器可以检查 TCP 有效负载大小是否等于 MSS,但这需要网络硬件记住经过它的每个 TCP 流的 MSS。只需检查 PUSH 位就简单多了。
原则上,如果操作系统阻止传递包含不完整 TLS 记录的 TCP 段,则可以获得一些性能,因为用户空间中的 TLS 实现通常不会开始解密,直到它看到 TLS 记录的最后一个字节,因为这非常重要。最后一个字节通常包含填充大小并告诉解密数据的大小。
不过,我怀疑第二种类型的阻碍是否会发生在任何地方。
无论如何,数据不会在接收缓冲区中等待。
TCP 应用程序必须竭尽全力让 TCP 层批量处理一些数据包并提供完整的数据缓冲区。
事实上,看到应用程序分配 64KB 缓冲区来接收数据并收到大量 1480/1472 字节消息,这有点令人沮丧。