TCP报文
TCP 报文由首部和数据两部分组成,数据部分如果是 HTTP 协议就是 HTTP 报文,所以主要看 TCP 首部,TCP 首部中的各个字段指示决定 TCP 的工作原理。
源端口和目的端口
源端口就是客户端发起请求的端口号,目的端口就是接收请求和发送响应的端口,例如 HTTP 协议的服务器响应端口就是80
或者443
等。
序号 Seq
TCP 连接是面向字节流的,也就是组成 TCP 报文的最小单位是字节,但是在一个 TCP 连接中,发送者和接收者都可以发送报文,并且还能连续依次发送多个报文;比如说,客户端发给服务器 3 个报文,然后服务器又响应发回 3 个报文这样子。为了在传输过程中排队进行不会混乱,那么就需要序号来保证。
在一个 TCP 连接中每一个字节都要按顺序编号,那么在 TCP 首部中的序号seq
就表示本 TCP 报文所发送的数据的第一个字节的序号,例如,当前 TCP 报文序号是 200,当前报文的数据部分长度是 100,那么如果这个报文后面还有报文要传输,则下一个报文的首部的序号是 300,就这么按顺序排列!
在首部中,序号固定占 4 个字节,也就是 32 位二进制数字,所以序号范围值是[0, 2^32-1]
,从[0, 4294967696]
,一个 TCP 连接的序号值不一定从 0 开始,可以在这个范围内随便选一个值,当报文段的序号值到达 2^32-1 时,下一个序号就回到 0 开始。
这个字段是 TCP 连接中最重要的字段!
确认号 Ack
确认号ack
是指示对方下一次发送的第一个 TCP 报文的首部序号值,当 TCP 建立连接后它的值是收到的最后一个 TCP 报文的首部序号值加上数据长度值,例如服务器收到的最后一个报文的首部序号值是 200,数据长度是 200,那么服务端下一次发送给客户端的报文段的第一个报文的首部确认号应该是 200+200=400,当客户端收到后,下一次发送 TCP 报文段的第一个报文首部序号就是 400。
所以,当确认号为 N 时,表明 N-1 之前的报文段的数据都收到了。
数据偏移
TCP 报文的首部长度,这个数字用 4 位二进制表示,1111
最大位 15,这个值的单位是 32 位字(以 4 字节长的字为计算单位),所以首部长度最大为 15*4 = 60 个字节。
保留
保留部分占 6 位,暂不知道用处;
控制位
保留后面接有控制位部分,每个控制位都使用二进制数字0
和1
来表示是否激活
紧急 URG
当 URG 的值为 1 时,表示该报文有紧急数据,应该尽快传送,这时 TCP 就会调整整个 TCP 报文段的传送顺序,将 URG 的值为 1 的紧急报文放在整个报文段的最前面,由于此时报文段的序列号已经被打乱了,所以还需要一个紧急指针(Urgent Pointer)来指示紧急数据末尾在报文段中的位置。
确认 ACK(ACKnowledgment)
确认标记位是建立 TCP 连接时使用的关键字段,不要和确认号ack
混淆在一块了,ACK
只有两个值;当 TCP 报文首部的ACK = 1
时,表明当前报文的发送者已经做好了连接建立的准备,并且只有当ACK = 1
时,确认号字段才有效;当ACK = 0
时,确认号无效。
TCP 规定,在连接建立后所有传送的报文段都必须将 ACK 置1
,也就是准备正式传输数据了。
为了区分确认标记和确认号,通常将确认标记写作全大写字母ACK
,而确认号用全小写字母表示ack
。
推送 PSH(Push)
当两个应用程序在通信时,有时一端的应用程序希望在键入一个命令后里立即能收到对方的响应。在这种情况下,TCP 就可以使用推送操作。这时,发送方 TCP 把首部的 TCP 置 1,并立即创建一个报文段发送出去,接收方收到后,就尽快交付给应用程序。
复位 RST(Reset)
当RST = 1
时,表示 TCP 连接中出现严重差错,必须释放连接,然后重新建立连接。RST = 1
还用来拒绝一个非法的报文段或拒绝打开一个连接。
同步 SYN(SYNchronization)
SYN
是 TCP 建立连接的三次握手过程中的重要字段,用于 TCP 建立连接时同步序号。
- 当客户端发起向服务器的第一个连接请求时,TCP 报文首部的
SYN = 1
,且会在[2,2^32-1]
之间选择一个序号seq = x
,发送完以后客户端进入SYN-SENT
状态(同步已发送); - 服务端收到客户端请求 TCP 报文后,如果同意建立连接,则会向客户端发送确认连接的 TCP 报文,这时的 TCP 报文段首部
SYN = 1
,同时将自己的确认标记位置为ACK = 1
表示已经准备好建立连接了,而服务端也会选择自己的数据序号seq = y
放在 TCP 报文的首部,同时因为上个 TCP 报文没有携带任何数据,这时的确认号就是请求报文的序号加 1 即ack = x+1
;发送完以后服务端变成SYN-RCVD
状态; - 客户端在收到服务端的确认连接 TCP 报文后,要再次向服务端发送确认连接的回应,于是发送确认连接 TCP 报文,将自己的确认连接标记
ACK = 1
;同时根据服务端发回的确认号设置首部序号值seq = x+1
;根据服务端的序号设置首部的确认号ack= y+1
,发送完以后客户端进入ESTABLISHED
状态 - 当 B 收到 A 的回应后,B 也进入
ESTABLISHED
状态
终止 FIN(Finish)
这也是 TCP 连接必须掌握的字段,用来终止 TCP 连接的字段,当FIN = 1
时,就表示要求终止连接。
窗口(window)
窗口指的是发送本报文段的一方的接收窗口,窗口值用来限制接收方允许对方发送的数据量(以字节为单位,不包含首部的长度),因为接收方的数据缓存空间是有限的。
检验和
紧急指针(Urgent Pointer)
配合紧急 URG 首部使用的
选项
长度可变,最长可达 40 字节,如果没有选项
这个部分,TCP 报文首部长度就是 20 字节。
MSS
MSS,Maximum segment size,MSS 是每个 TCP 报文的数据部分的最大长度。