TCP
基本认识
TCP
是 面向连接的、可靠的、基于字节流的传输层通信协议。
1 | 0 1 2 3 |
源端口(Source Port
)
源端口,16
位
目标端口(Destination Port
)
目标端口,16
位
序列号 (Sequence Number
)
TCP
是面向字节流的协议,通过 TCP
传输的字节流的每个字节都分配了序列号,序列号(Sequence number
)指的是本报文段第一个字节的序列号。
序列号加上报文的长度,就可以确定传输的是哪一段数据。序列号是一个 32
位的无符号整数,达到 2^32-1
后循环到 0
。
在 SYN
报文中,序列号用于交换彼此的初始序列号,在其它报文中,序列号用于保证包的顺序。
因为网络层(IP
层)不保证包的顺序,TCP
协议利用序列号来解决网络包乱序、重复的问题,以保证数据包以正确的顺序组装传递给上层应用。
初始序列号 (Initial Sequence Number, ISN
)
在建立连接之初,通信双方都会各自选择一个序列号,称之为初始序列号。在建立连接时,通信双方通过 SYN
报文交换彼此的 ISN
序列号回绕
确认号 (Acknowledgment Number
)
TCP
使用确认号(Acknowledgment number, ACK
)来告知对方下一个期望接收的序列号,小于此确认号的所有字节都已经收到
头部长度 (Data Offset
):
只有 4
位, 取值范围 0~15
, 表示 TCP
头长度为 32位(4字节)
的数量。TCP
头(甚至包括选项)的长度是 32
位的整数倍。例如 DOffset
的值为 0111
, 则该TCP包头的长度为 7 * 4 = 28
TCP Flags
SYN(Synchronize)
:用于发起连接数据包同步双方的初始序列号ACK(Acknowledge)
:确认数据包RST(Reset)
:这个标记用来强制断开连接,通常是之前建立的连接已经不在了、包不合法、或者实在无能为力处理FIN(Finish)
:通知对方我发完了所有数据,准备断开连接,后面我不会再发数据包给你了。PSH(Push)
:告知对方这些数据包收到以后应该马上交给上层应用,不能缓存起来
窗口大小 (Window Size
)
窗口大小字段是接收方用来控制发送方数据流量的机制。它表示接收方当前允许发送方发送但尚未确认的数据字节数。通过动态调整窗口大小,TCP
可以有效地进行流量控制,防止发送方数据发送过快导致接收方缓存溢出。
TCP
协议窗口大小只有 16
位,最大窗口大小为 65535
字节(64KB
), 在今天显然不够用,所以 TCP
协议引入了 TCP 窗口缩放 选项,作为窗口缩放的比例因子,比利因子的值在 0~14
,其中 0
表示不缩放,最大值为 14
。比例因子可以将窗口扩大到原来的 2
的 n
次方,比如窗口大小缩放前为 1050
,缩放因子为 7
,则真正的窗口大小为 1050 * 128 = 134400
窗口缩放选项
由于窗口大小字段只有 16
位,最大值为 65535
字节,这对于高带宽-延迟产品 (BDP
) 的网络可能不够。为了解决这个问题,TCP
窗口缩放选项 (Window Scale Option
) 被引入,用于扩展窗口大小的范围。
窗口缩放选项在 TCP
连接建立时通过 SYN
包交换协商。窗口缩放因子 (Window Scale Factor
) 表示允许窗口大小值左移的位数,从而有效地扩展窗口大小的范围。
计算实际窗口大小
实际的窗口大小计算如下:
$$Actual Window Size = Window Size \times 2 ^{Window Scale Factor}$$
示例(带窗口缩放)
假设窗口大小字段的值是 8192
(十进制),窗口缩放因子是 3
:
$Actual Window Size = 8192 \times 2 ^ 3 = 8192 \times 8 = 65536 $ bytes
这表示接收方可以接受最多 65536
字节的未确认数据。
可选项 (Options
)
只有 (DOffset > 5
) 才有此数据,
可选项的格式:
一个字节的
Kind
No-Operation
: 无操作。
一个字节的
Kind
, 一个字节的option-length
,和真实的option data
MSS
:最大段大小选项,是TCP
允许的从对方接收的最大报文段SACK
:选择确认选项Window Scale
:窗口缩放选项