数据传输阶段的变化完成了 , 三次握手后,客户端就可以发送第一个 ** **TCP 数据报文了,假设客户端即将要发送 10 字节的数据,流程图下:
文章插图
在这里插入图片描述
客户端发送 10 字节的数据,通常 TCP 数据报文的控制位是 [PSH, ACK],此时该 TCP 数据报文的序列号和确认号分别设置为:
- 序列号设置为 client_isn + 1 。客户端上一次发送报文是 ACK 报文(第三次握手),该报文的 seq = client_isn + 1,由于是一个单纯的 ACK 报文,没有携带用户数据,所以 len = 0 。根据公式 1(_序列号 = 上一次发送的序列号 + len_) , 可以得出当前的序列号为 client_isn + 1 + 0 , 即 client_isn + 1 。
- 确认号设置为 server_isn + 1 。没错 , 还是和第三次握手的 ACK 报文的确认号一样,这是因为客户端三次握手之后,发送 TCP 数据报文 之前,如果没有收到服务端的 TCP 数据报文,确认号还是延用上一次的,其实根据公式 2 你也能得到这个结论 。
接着,当服务端收到客户端 10 字节的 TCP 数据报文后,就需要回复一个 ACK 报文,此时该报文的序列号和确认号分别设置为:
- 序列号设置为 server_isn + 1 。服务端上一次发送报文是 SYN-ACK 报文,序列号为 server_isn,根据公式 1(_序列号 = 上一次发送的序列号 + len 。特殊情况,如果上一次发送的报文是 SYN 报文或者 FIN 报文,则改为 + 1_),所以当前的序列号为 server_isn + 1 。
- 确认号设置为 client_isn + 11。服务端上一次收到的报文是客户端发来的 10 字节 TCP 数据报文,该报文的 seq = client_isn + 1,len = 10 。根据公式 2(_确认号 = 上一次收到的报文中的序列号 + len_),也就是将「收到的 TCP 数据报文中的序列号 client_isn + 1,再加上 10(len = 10) 」的值作为了确认号,表示自己收到了该 10 字节的数据报文 。
之前有读者问 , 如果客户端发送的第三次握手 ACK 报文丢失了,处于 SYN_RCVD 状态服务端收到了客户端第一个 TCP 数据报文会发生什么?刚才前面我也说了,发送的第一个 「TCP 数据报文的序列号和确认号」都是和「第三次握手的 ACK 报文中序列号和确认号」一样的,并且该 TCP 数据报文也有将 ACK 标记位置为 1 。如下图:
【TCP 序列号和确认号是如何变化的?】
文章插图
在这里插入图片描述
所以,服务端收到这个数据报文,是可以正常完成连接的建立,然后就可以正常接收这个数据包了 。
四次挥手阶段的变化最后,我们来看看四次挥手阶段中,序列号和确认号的变化 。
数据传输阶段结束后 , 客户端发起了 FIN 报文,请求服务端端开该 TCP 连接,此时就进入了 TCP 四次挥手阶段,如下图 。
文章插图
在这里插入图片描述
客户端发送的第一次挥手的序列号和确认号分别设置为:
- 序列号设置为 client_isn + 11 。客户端上一次发送的报文是 [PSH, ACK] ,该报文的 seq = client_isn + 1, len = 10,根据公式 1(_序列号 = 上一次发送的序列号 + len_),可以得出当前的序列号为 client_isn + 11 。
- 确认号设置为 server_isn + 1 。客户端上一次收到的报文是服务端发来的 ACK 报文,该报文的 seq = server_isn + 1,是单纯的 ACK 报文,不携带用户数据,所以 len 为 0 。那么根据公式 2(确认号 = 上一次收到的序列号 + len) , 可以得出当前的确认号为 server_isn + 1 + 0 (len = 0),也就是 server_isn + 1 。
- 序列号设置为 server_isn + 1 。服务端上一次发送的报文是 ACK 报文,该报文的 seq = server_isn + 1,而该报文是单纯的 ACK 报文,不携带用户数据,所以 len 为 0,根据公式 1(_序列号 = 上一次发送的序列号 + len_),可以得出当前的序列号为 server_isn + 1 + 0 (len = 0),也就是 server_isn + 1 。
- 确认号设置为 client_isn + 12 。服务端上一次收到的报文是客户端发来的 FIN 报文 , 该报文的 seq = client_isn + 11,根据公式 2(_确认号= _上一次_收到的序列号 + len,特殊情况,如果收到报文是 SYN 报文或者 FIN 报文 , 则改为 + 1_),可以得出当前的确认号为 client_isn + 11 + 1,也就是 client_isn + 12 。
推荐阅读
- 二 SpringCloud - Eureka注册中心,feign远程调用,hystrix降级和熔断
- 其三 Gitea 1.18 功能前瞻:增强文本预览效果、继续扩展软件包注册中心、增强工单实用功能、完善了用户邀请机制和SEO
- 华为watch3pro尊享版和时尚版区别_哪款更值得入买
- 雅萌ace和max的区别_雅萌ace和max的参数
- 真我q3和q3s有什么区别_真我q3和q3s参数对比
- SQL 报表制作和整形
- 跟我学Python图像处理丨图像特效处理:毛玻璃、浮雕和油漆特效
- AngouriMath:用于C#和F#的开源跨平台符号代数库
- 荣耀v40和华为nova8性价比哪个高
- 【vue2】Style和Class,条件,列表渲染,双向数据绑定,事件处理