TCP报头中的URG 与 PSH标志不同之处与作用

TCP报头

众所周知TCP 是面向连接的、可靠的、基于字节流的传输层通信协。那么TCP是用什么来支持保证数据的可靠呢?答案就是它头部包含众多格式字段分别表示不同的含义,通信双方通过约定好的方式去解读和设置这些字段,从而保证TCP 的可靠性。

TCP头部格式图:

TCP报头中的URG 与 PSH标志不同之处与作用

本文忽略RFC 3168为拥塞通知添加的CWR和ECE标志

特殊标识位

TCP 头部包含有几个一比特(ont-bit)的布尔字段,用来影响TCP 连接数据流。其中四个标志位用于控制TCP 连接的建立、维护和拆除。

  • SYN 启动连接
  • ACK 确认收到
  • FIN 关闭连接
  • RST 中止连接

详述:

  1. 同步SYN(SYNchronization)标志:当 SYN 被置为 1,而 ACK 为0时, 说明这是一个连接请求报文段,若对方同意建立连接,则应在应答报文中将 SYN 和 ACK 都置为 1。
  2. 确认ACK(ACKnowlegment):仅当 ACK 被置为 1 时,确认号字段才有效。 TCP 规定在连接建立后的所有传输报文都必须把 ACK 置 1。
  3. 终止FIN(Finish):用来释放一个连接。 当 FIN 被置 1 时,说明此报文的发送方的数据已经发送完毕,要求释放连接。
  4. 复位RST(Reset):当该位有效时,表面 TCP 连接中出现严重错误,比如一方中途崩溃,或者网络极度拥塞,导致大面积丢包,数据长时间无法到达对方,则接下来的传输必须重新建立。该位还可以用来拒绝一个非法的报文段。

除了以上标志位,还有两个不是很“出名”的标志位。它们就是 PSH(Push)URG(Urgent)

The PSH Flag

理解 PSH 标志之前,首先要知道 TCP 缓冲区的是如何工作的。TCP工作在在 OSI 模型中的第四次传输层,它对上层提供读取和写入的简单套接字,隐藏的数据之间通信分组的复杂性。为了允许应用程序随时从该套接字读取和写入,在接收方和发送方都有对应的缓冲区。

发送方和接受方:

TCP报头中的URG 与 PSH标志不同之处与作用

当发送多个最大段大小(MSS)的数据(例如,传输大文件)时,缓冲器允许更有效地传输数据。然而,在处理一些要尽可能快地传输的实时应用程序时,大型缓冲区会带来危害。比如,我们在使用 ssh协议远程登录到服务器时。如果 TCP 一直等待,直到所输入的数据填满整个数据包才发送的话,发送一个两个字符的数据包,必须要先输入一千字符。太糟糕。

PSH 标志的作用就在这里,当PSH 被置为1 时, 会被立即推出,不会等待其他数据进入缓冲区。当接受端收到 PSH 被置 1 的数据包时,立即将该分段上交到对应的应用程序。即有如下作用:

  • 通知发送方立即发送数据。
  • 接收方立即将数据推送到应用程序。

这个标志是怎么被设置的?

这个标志是在TCP层清空发送缓存,并将报文段交给IP层的时候设置的(相当于表示一次TCP层的发送操作)。(还有一点需要注意:大多数的API没有向应用层提供通知TCP层设置PUSH标志的方法,据说是因为很多实现程序认为PUSH标志已经过时,而一个好的TCP实现能够自行决定何时设置这个标志。

下图是我在使用XShell远程登录到虚拟机中的服务器时所抓的包并过滤出ssh协议的数据:

TCP报头中的URG 与 PSH标志不同之处与作用

我观察本次抓包所有的使用shh协议的数据包,PSH都有效,防止被缓冲。所以这也是为什么 SSH 协议基于 TCP 的同时又可以对用户输入的短小指令可以快速响应的原因。

The URG Flag

URG 标志用于通知接收方,数据段内某些数据是需要紧急处理的,应该被优先考虑。接收方收到 URH标志有效的数据报时,回去检测 TCP 报头中的16 位字段 紧急指针。 该字段指示从第一个字节计数的段中的数据时多少紧急处理的。

TCP报头中的URG 与 PSH标志不同之处与作用

跟上网上所述,此标志位逐渐被淘汰。原因是定义和实现上的混乱。

想详细了解 URG 的实现可阅读下面我在网上看到的这篇文章。我觉得很(看)高(不)深(懂)。

TCP的URG标志和内核实现