目录
前言:
三次握手:
四次挥手:
又是一篇记录自己学习+日后复习的博客。目前正在学习爬虫,但是没想到学习爬虫需要这么多web前端的知识@A@. 总之说到“三次握手和四次挥手”的时候,总是:嗯,了解这么个大致过程,但其中具体的原理还不太了解。本文不涉及别的内容,因为也不会。收集了一些资料,也看了CSDN上一些大佬写的博客(有些点击量挺高的,里面还有一些错误,总之对新手不太友好)。
于是我来“新手友好”。
这张图来自百度。左边的蓝色箭头表示“时间”。
1. 客户端想要和服务器建立联系,首先发送TCP连接的请求报文(一个包),设置SYN=1的标识位,其中包含一个seq = x 的序号。
①: SYN = 1, seq = x
这里的SYN 指的是 sychronize: 表示建立联机,服务器通过SYN识别包的性质。
seq = sequence,表示序号,序号随机生成。
(我个人的理解是“客户端的识别码”,不知道这样理解是否准确?)
2. 服务器接收到请求,回复TCP请求报文,此时SYN依旧为1,并生成ack,此时ack的值是客户端发送的seq的值+1,即: ack = x + 1,并生成一个新的序号seq = y 这个序号用以区别客户端的序号,并且也是随机生成。
②:SYN = 1, ack = x + 1, seq = y
(我理解这里的ack = x + 1,的意思是:我收到了你序列号为x的序列码,然后我返回给你一个seq = y,你看看能不能收到我发出的消息?)
这里的ack 和ACK不一样,ACK (ACKNOWLEDGEMENT)这类大写缩写,指的是标识位,用来识别包的性质,而ack(acknowledgement number)指的是“确认号”,即收到seq = x的数据包后,回复 ack = x + 1 来确认。
(但我还是有问题的,有的教程中的图片会把ACK当作ack来写。这个问题我还没有查询清楚,所以暂且将ACK 和 ack分开比较好。如果有哪位大佬走过路过了解这个内容,请一定在评论区告知我一下!非常感谢!)
这一步成功表明:客户端发送正常,服务器接收正常
3. 客户端收到请求, (就是服务器发的那个),他肯定要回复给服务器,告知服务器:我收到了你的回复。所以又要发一个包: SYN = 1, ack = y + 1, seq = x + 1。
③:SYN = 1, ack = y + 1, seq = x + 1
这时候可以确认,客户端发送、接收正常;服务器发送、接收正常,可以开始数据传输了。
这个图依然来自于百度,整个过程非常清楚。
需要注意:
FIN码是第一次挥手客户端发送关闭请求时出现;第三次服务器挥手时出现。
为什么?其实这也是为什么会“四次挥手”的原因。
1. 在数据传输过程中,客户端想要关闭传输,客户端进入FIN-WAIT-1的状态,并对服务器进行第一次挥手:给服务器发了一个FIN的包,加一个seq = u 的序列号。这个序列号依然是随机生成!作用和三次挥手中的作用差不多。
2. 服务器收到FIN 包后,告诉正在传输的应用进程:客户端想要断开链接,但我还有数据没发完呢。同时进入CLOSE-WAIT状态,服务端发送第二个包,即进行第二次挥手:ACK = 1, ack = u + 1,seq = v 。
有些CSDN博主写到二次挥手的时候,就会出现 seq 各种“乱飞”的情况,其实这里的seq和三次握手的seq本质上差不多,都是用来识别的。到此时,客户端和服务器只会随机生成两个不同的随机数:u 和 v。我的理解:这里客户端生成的ack是用来识别传输数据的。
而且要注意,为什么这里还没有停下呢?因为还有一部分数据需要传输,服务端先处理这些数据,再告诉客户端“我知道要结束进程啦”。此时数据传输时单向的。
3. 传输完数据,服务器再次向客户端发送FIN = 1的包,告诉客户端,我收到了你想要关闭程序的包。于是:FIN = 1, ACK = 1, seq = w, ack = u + 1。
新生成的序列号用以识别FIN包。
4. 客户端收到服务器的FIN包后,会返回:ACK = 1, seq = u +1, ack = w + 1
用来表示:你发的包,我收到了。
服务器收到客户端的第四个包,就会直接关闭。客户端也会等待两分钟后,直接关闭。
MSL最长报文段寿命Maximum Segment Lifetime是2分钟。
具体原因可以参考大佬的文:
TCP的四次挥手及为什么要等待2MSL_四次挥手为什么要等待2msl时间_Code@Z的博客-CSDN博客