TCP/IP 协议中的一些要点

引子

项目遇到一个需求,抽象出来就是需要 app 通过 socket 与另一个设备(非 Android)之间传输数据。由于数据传输是建立在裸的 socket 之上,因此双方传输数据需要私下拟定一个传输协议。我们参考 TCP 协议中的丢包重传机制,拟定了一个私有协议。下面主要解释下 TCP 协议中确认传机制和超时机制的要点。

TCP 协议

数据报格式

TCP 数据报格式

源端口、目的端口:标识端口号

数据序号:32位。表明发送数据报的顺序。一个字节对应一个序号。该序号表示该数据报中的数据字段的第一个字节对应的序号。用于记录发送方已发数据。

确认序号:期望收到的下一个数据报的序号。注意,这个确认号与上面的序号没有关系。因为TCP是全双工的协议。这个确认号是由发送方根据本地已接收的数据,计算出来的。用于记录发送方已收数据。

偏移:即报文头长度。之所以有这个字段是因为数据报中有可选选项这个不定长的数据。该字段以 32 比特为单位计数。没有可选选项时,该字段为 5。

标志位

  • ACK:该位为1则表明确认序号生效,0则表明无效。
  • PSH:带该标志位则表示接收方收到数据报便可送往应用程序,不必等缓冲区满才送。
  • RST:复位标志。用于由于崩溃或者其他原因而出现的错误连接。还可以用于拒绝非法的数据报或拒绝连接请求。
  • SYN:仅用于三次握手建立连接。
  • FIN:用于四次挥手释放链接。使通信双方释放连接资源。

窗口字段:16位长。用于告知对方当前的接收窗口大小。

校验和:校验 TCP 数据报首部、数据和伪 TCP 首部。伪首部包括了 32 位源 IP 地址,32 位目的 IP 地址,8 位填充 0,8 位协议,16 位 TCP 数据报长度。

紧急指针:URG为1时有意义

可选项:长度可变、最长40字节。比较重要的可选项:

  • MMS:最大报文长度
  • SACK:选择确认
  • 时间戳:计算往返时间;

由上可见,TCP 数据报最小就只有头,一共 20 字节。

确认机制

  1. 采用累计确认机制:接收方对收到的数据报进行缓存,并对每一个收到的数据报都回复ACK。
  • 如果缓存中没有丢包空洞,那么回复ACK中确认字段就是期望收到的下一个数据报序号
  • 如果缓存中有丢包空洞,那么回复ACK中确认字段就是第一段空洞的第一字节序号。并且现在普遍实现都会带上 SACK 选项:数据字段就会有丢包区间 [startSeq_1, endSeq_1], [startSeq_2, endSeq_2]...
  1. Delay ACK:延时确认:https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment

延时确认机制允许接收方延迟 500ms 再对多个收到的数据报进行确认。但是如果一个数据报中携带的数据达到了 MSS,那么接收方需要立即回复 ACK 进行确认。

重发超时如何确定?

超时重传

server 端通过计算每个数据报的ACK时间来动态计算 RTT,从而动态计算出超时时间 RTO

快速重传

如果server端连续收到3个相同ACK数据报,那么就立刻重传,不用等RTO超时

由上可见,采用的是动态计算超时时间 + 快速重传

每个数据报长度

每个数据报都不一样,但是尽可能以MSS的长度进行发送。理想情况是, MSS正好是IP中不会被分片处理的最大数据长度。

流控制

协议中带有窗口大小字段,由接收端通知发送端它的接收窗口大小,以避免发送端发送过多的数据。

接收端窗口满时,窗口大小字段为 0

你可能感兴趣的:(TCP/IP 协议中的一些要点)