TCP中的三次握手与四次挥手
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
数据报
首先要谈TCP中的三次握手与四次挥手我们必须知道TCP中的数据报。
其中一行有32位,也就是4个字节。
第一行,源端口号与目的端口号各占16位,这两者代表发送端与接受端的地址。
第二行,是序号(seq)有32位。
第三行,是确认序号(ack)有32位,注意要和下面的ACK区分开来。
第四行,比较重要的就是6个标志位,不过常用的就3个。
- ACK:确认标志位,只有1位,即只能表示1(有效)和0(无效)。
- SYN:代表发起一个新的连接,只有1位。
当SYN=1而ACK=0时,表明这是一个连接请求报文。对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1。因此,SYN置1就表示这是一个连接请求或连接接受报文。
- FIN:代表结束一个连接,只有1位。
TCP三次握手
我上网搜了两张图片,应该大致能说明这个问题。
TCP怎样才能保证可靠的传输任务,就是通过三次握手,也可以说三次握手是TCP建立连接时使用的方案。如下图所示:
注:seq应该位32位!但是为了方便画图所以用10000代替。
x
(1)首先由Client发出请求连接即 SYN=1,确认标志位ACK=0,序号seq=10000(假设)
(2)然后 Server 进行回复确认,即 SYN=1,seq=20000,确认标志位ACK=1,确认序号ack=10001(10000 + 1),此时服务端接收数据没有问题,但是客户端接收数据不知道会不会出问题!
(3)最后 Client 再进行一次确认,但不用请求连接SYN 了,这时即为确认标志位ACK=1,序号seq=10001(表示Client发出的第二条信息,所以seq递增加一),确认序号ack=20001,此时客户端接受服务端的数据没有问题。
TCP四次挥手
四次挥手是指TCP要断开连接时做的事情。
(1)由Client发起关闭连接的请求,即FIN=1,seq=25368(以上述的10000,每发送一条就+1,一直加到了25368)
(2)Server端收到了关闭请求,所以要做出应答确认标志位ACK=1,确认序号ack=25369,
(3)Server端将要发送的数据发完之后,就最后回复一条FIN=1,序号位10568。
(4)客户端收到后回复一个ACK=1,表示收到了,ack=10569,服务器端关闭,2MSL后客户端关闭。
简单的来说就是:
(1)假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你(服务器端)还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。
(2)所以你(服务器端)先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。
(3)当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。
(4)Client端收到FIN报文后,就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。Server端收到ACK后,"就知道可以断开连接了"。
Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!(是服务端先关闭,后客户端关闭)
为什么连接的时候是三次握手,关闭的时候却是四次握手?
因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。
但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。
只有等到Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
为什么TIME_WAIT状态需要经过2MSL(最大报文段生存时间)才能返回到CLOSE状态?
虽然按道理,四个报文都发送完毕,我们可以直接进入CLOSE状态了,但是我们必须假设网络是不可靠的,有可能最后一个ACK丢失。所以TIME_WAIT状态就是用来重发可能丢失的ACK报文。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
2021-04-12 班级考勤管理系统