22-TCP 协议(PSH 标志)

1. PSH 标志位

从你第一次抓包以来,PSH 标志位几乎与你形影不离。它的英文单词是 PUSH,表示“推”的意思。

1.1 接收缓冲区和发送缓冲区

在谈 PSH 标志位前,先来说说 TCP 双方是如何发送数据的。

假设有发送方 A 和接收方 B。发送方有一个发送缓冲区,接收方有一个接收缓冲区,见图 1。进程 A 发送”hello”, “world” 后,只是将这些数据写到自己的发送缓冲区,为了能讲清 PSH 的作用,不妨假设我们可以自己指定 PSH 标志。在图 1 所示的情况中,第一次 write 没有指定 PSH 标记,而第二次指定了 PSH 标志。


这里写图片描述
图1 TCP 协议中的发送缓冲区与接收缓冲区

接收进程 B,接收到 TCP 报文后,将数据放入到接收缓冲区。

1.2 PSH 的作用

在 1.1 节中,TCP 模块什么时候将数据发送出去(从发送缓冲区中取数据),以及 read 函数什么时候将数据从接收缓冲区读取都是未知的。

如果使用 PSH 标志,上面这件事就确认下来了:

  • 发送端

对于发送方来说,由 TCP 模块自行决定,何时将接收缓冲区中的数据打包成 TCP 报文,并加上 PSH 标志(在图 1 中,为了演示,我们假设人为的干涉了 PSH 标志位)。一般来说,每一次 write,都会将这一次的数据打包成一个或多个 TCP 报文段(如果数据量大于 MSS 的话,就会被打包成多个 TCP 段),并将最后一个 TCP 报文段标记为 PSH。

当然上面说的只是一般的情况,如果发送缓冲区满了,TCP 同样会将发送缓冲区中的所有数据打包发送。

  • 接收端

如果接收方接收到了某个 TCP 报文段包含了 PSH 标志,则立即将缓冲区中的所有数据推送给应用进程(read 函数返回)。

当然有时候接收缓冲区满了,也会推送。

接下来,通过实验来理解 PSH 标志位的作用。这个实验是经过设计的,只是为了方便你理解。

2. 实验

2.1 环境准备

服务器:unp/protocol/tools/tcpserver/psh_serv.c,部署在 Linux 上。
客户端:unp/protocol/tools/winclient/psh_client.cpp,部署在 Windows 上。

psh_serv 服务器从接收方接收数据,进行循环 read,每一次 read 返回会在屏幕打印读取的字节数。

psh_client 客户端向服务器发送数据,循环 write,每一次 write blocksize 个字节,循环 write count 次。blocksize 和 count 由命令行参数控制。

接下来我们进行两个实验。

2.2 实验1

客户端循环 write 8 次,每次 write 1024 字节

  • Linux 上启动服务器
$ ./psh_serv 192.168.80.129 8000 8192

最后一个参数 8192 指明了 read 函数的一次要读取的字节数。

  • Windows 上启动 OmniPeek 抓包,同时启动客户端
psh_client.exe 192.168.80.129 8000 8 1024

最后两个参数 8 1024 表示客户端循环写数据 8 次,每次写 1024 字节。

  • 结果


这里写图片描述
图2 8 次写数据,每次写 1024 字节


这里写图片描述
图3 服务器每一次循环只 read 了 1024 字节就返回

从图 2 和图 3 我们可以看到,因为客户端每一次 write 后,发送的 TCP 报文都带有 PSH 标志位,接收方收到带有 PSH 的报文后,会立即推送给接收进程。

2.3 实验2

客户端只写一次数据,大小为 8192 字节

  • Linux 上启动服务器
$ ./psh_serv 192.168.80.129 8000 8192

最后一个参数 8192 指明了 read 函数的一次要读取的字节数。

  • Windows 上启动 OmniPeek 抓包,同时启动客户端
psh_client.exe 192.168.80.129 8000 1 8192

最后两个参数 1 8192 表示客户端循环写数据 1 次,每次写 8192 字节。

  • 结果


这里写图片描述
图4 一次性发送 8192 字节


这里写图片描述
图5 接收方一次性将所有数据全部 read

从图 4 中可以看到,一次 write 了 8192 字节到缓冲区,但是因为 MSS 的限制(服务器端 MSS 为 1460,而客户端只有 1260),客户端会在两个 MSS 之间选一个最小值来确认发送 TCP 报文段大小。

图 4 中,客户端将 8192 字节的数据拆分成了 7 个报文段,注意只有最后一个报文段有 PSH 标志位。

只要接收方的缓冲区没有满,就会一直等待,直到接收到一个带有 PSH 标志的报文,read 才会返回。

3. 总结

  • 掌握 PSH 的含义
说明:本文转自--Allen--,用于学习交流分享,仅代表原文作者观点。如有侵权,请联系我们删除~