通俗易懂理解TCP协议三次握手和四次挥手及其常见问题

TCP协议三次握手和四次挥手

《通俗易懂理解TCP协议三次握手和四次挥手及其常见问题》

三次握手

形象比喻
将小明当作客户端,小红当作服务器端,两人写信告白:
第一次握手:
小明告诉小红:我喜欢你。
第二次握手:
小红告诉小明:我知道了,我也喜欢你。
此时小红并不确定小明是否收到了告白信,直到
第三次握手:
小明回信:我也知道了,我们在一起吧。此时才真正建立连接。
《通俗易懂理解TCP协议三次握手和四次挥手及其常见问题》

标记位解释
SYN请求号标记位
ACK确认号标记位
seq序号,代表请求方将会发送的数据的第一个字节编号
ack返回的确认号,代表接收方收到收据后(也就是前面说的seq),代表希望对方下一次传输数据的第一个字节编号
状态位解释
CLOSEDclient处于关闭状态
LISTENserver处于监听状态,等待client连接
SYN-RCVD表示server接受到了SYN报文,当收到client的ACK报文后,它会进入到ESTABLISHED状态
SYN-SENT表示client已发送SYN报文,等待server的第2次握手
ESTABLISHED表示连接已经建立
  • 第一次握手:客户端第一次发送一条连接请求数据,SYN = 1,ACK = 0就是代表建立连接请求,发送的具体数据第一个字节编号记为x,赋值seq。

  • 第二次握手:服务端收到请求后,返回 客户端的SYN = 1,加上自己的确认号ACK=1,发送的具体数据第一个字节编号记为y,赋值seq,希望客户端下一次返回编号x + 1个字节为止的数据,记为ack = x + 1。

客户端得出客户端发送接收能力正常,服务端发送接收能力也都正常,但是此时服务器并不能确认客户端的接收能力是否正常

  • 第三次握手:客户端收到服务端返回的请求确认后,再次发送数据,原封不动返回ACK = 1,这里就不需要再发送 SYN=1了,为什么呢?因为此时并不是跟服务端进行连接请求,而是连接确认,所以只需要返回ACK = 1代表确认,同样的,发送的具体数据第一个字节编号记为seq = x + 1,希望服务端下次传输的数据第一个字节编号记为ack = y + 1

为什么TCP建立连接时候,要进行3次握手,2次不行吗?
一句话的答案:主要目的:防止server端一直等待,浪费资源,

如果建立连接只需要2次握手,可能会出现的情况

假设client发出的第一个连接请求报文段,因为网络延迟,在连接释放以后的某个时间才到达server 。
本来这是一个早已失效的连接请求,但server收到此失效的请求后,误认为是client再次发出的一个新的连接请求 。
于是server就向client发出确认报文段,同意建立连接。
如果不采用“3次握手”,那么只要server发出确认,新的连接就建立了 。
由于现在client并没有真正想连接服务器的意愿,因此不会理睬server的确认,也不会向server发送数据 。
但server却以为新的连接已经建立,并一直等待client发来数据,这样,server的很多资源就白白浪费掉了
采用“三次握手”的办法可以防止上述现象发生 ,例如上述情况,client没有向server的确认发出确认,server由于收不到确认,就知道client并没有要求建立连接。

四次挥手

形象比喻
恋爱之后,小明和小红煲电话粥。依旧将小明当作客户端,小红当作服务器端。小明跟小红说话,
第一次挥手:
小明说:我说完了。
第二次挥手:
小红说:好的,我知道了,我还没说完。
小红继续吧啦吧啦,说完之后
第三次挥手:
小红告诉小明:我说完了。
第四次挥手:
小明收到后告诉小红:好的,我知道了。等了2MSL之后小明挂断了。
如果此时小红说完,等了2MSL,小明一直不出声,这个时候就会重新说一次:我说完了。直到收到小明最后的回复,才挂断电话。
《通俗易懂理解TCP协议三次握手和四次挥手及其常见问题》

状态位: FIN = 1:代表要求释放连接

  • 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
  • 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
  • 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
  • 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手

为什么建立连接是三次握手,关闭连接确是四次挥手呢?

建立连接的时候, 服务器在LISTEN状态下,收到建立连接请求的SYN报文后,把ACK和SYN放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的FIN报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了,所以己方可以立即关闭,也可以发送一些数据给对方后,再发送FIN报文给对方来表示同意现在关闭连接,因此,己方ACK和FIN一般都会分开发送,从而导致多了一次。为了确保正确关闭连接,所以需要四次。

TIME_WAIT状态有什么作用,为什么主动关闭方没有直接进入CLOSED状态释放资源?

答:防止连接关闭时四次挥手中的最后一次ACK丢失:如果主动关闭方进入CLOSED状态后,被动关闭方发送FIN包后没有得到ACK确认,超时后就会重传一个FIN包。如果客户端没有TIME_WAIT状态而直接进入CLOSED状态释放资源,下次启动新的客户端就可能使用了与之前客户端相同的地址信息,有两个危害,第一种是这个刚启动的新的客户端绑定地址成功时,就会收到了一个重传的FIN包,对新连接就会造成影响。第二种是如果该新客户端向相同的服务端发送SYN连接请求,但是此时服务端处于LAST_ACK状态,要求收到的是ACK而不是SYN,因此就会发送RST重新建立请求。

为什么TIME_WAIT状态需要经过2MSL才能进入CLOSE状态?

答:MSL指的是报文在网络中最大生存时间。在客户端发送对服务端的FIN确认包ACK后,这个ACK包有可能到达不了,服务器端如果接收不到ACK包就会重新发送FIN包。所以客户端发送ACK后需要留出2MSL时间(ACK到达服务器器+服务器发送FIN重传包,一来一回)等待确认服务器端缺失收到了ACK包。也就是说客户端如果等待2MSL时间也没收到服务器端重传的FIN包,则就可以确认服务器已经收到客户端发送的ACK包

    原文作者:impact_factor
    原文地址: https://blog.csdn.net/impact_factor/article/details/119394391
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞