文章目录
- 🌲三次握手四次挥手总览
- 🍀三次握手(建立连接)
- 🌸为什么需要第三次通信 ?
- 🎄四次挥手(断开连接)
- 🌸四次挥手中涉及到的两个重要的状态
- ⭕总结
🌲三次握手四次挥手总览
在正常情况下,TCP要经过三次握手建立连接,四次挥手断开连接
整体过程如下:
该过程对应着很多种状态的转换
服务端状态转化
-
[CLOSED -> LISTEN] 服务器端调用listen后进入LISTEN状态,等待客户端连接;
-
[LISTEN -> SYN_RCVD] 一旦监听到连接请求(同步报文段),就将该连接放入内核等待队列中,并向客户端发送SYN确认报文。
-
[SYN_RCVD -> ESTABLISHED] 服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,可以进行读写数据了。
-
[ESTABLISHED -> CLOSE_WAIT] 当客户端主动关闭连接(调用close),服务器会收到结束报文段,服务器返回确认报文段并进入CLOSE_WAIT;
-
[CLOSE_WAIT -> LAST_ACK] 进入CLOSE_WAIT后说明服务器准备关闭连接(需要处理完之前的数据);当服务器真正调用close关闭连接时,会向客户端发送FIN,此时服务器进入LAST_ACK状态,等待最后一个ACK到来(这个ACK是客户端确认收到了FIN)
-
[LAST_ACK -> CLOSED] 服务器收到了对FIN的ACK,彻底关闭连接
客户端状态转化
-
[CLOSED -> SYN_SENT] 客户端调用connect,发送同步报文段;
-
[SYN_SENT -> ESTABLISHED] connect调用成功,则进入ESTABLISHED状态,开始读写数据;
-
[ESTABLISHED -> FIN_WAIT_1] 客户端主动调用close时,向服务器发送结束报文段,同时
进入FIN_WAIT_1; -
[FIN_WAIT_1 -> FIN_WAIT_2] 客户端收到服务器对结束报文段的确认,则进入FIN_WAIT_2,开始等待服务器的结束报文段;
-
[FIN_WAIT_2 -> TIME_WAIT] 客户端收到服务器发来的结束报文段,进入TIME_WAIT,并发出LAST_ACK;
-
[TIME_WAIT -> CLOSED] 客户端要等待一个2MSL(Max Segment Life,报文最大生存时间)的时间,才会进入CLOSED状态。
🍀三次握手(建立连接)
第1次握手:客户端发送一个带有SYN(synchronize)标志的数据包给服务端;
第2次握手:服务端接收成功后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了;
第3次握手:客户端再回传一个带有ACK标志的数据包,表示我知道了,握手结束。
其中:SYN标志位数置1,表示建立TCP连接;ACK标志表示验证字段。
三次握手过程详细说明:
1、客户端发送建立TCP连接的请求报文,其中报文中包含seq序列号,是由发送端随机生成的,并且将报文中的SYN字段置为1,表示需要建立TCP连接。(SYN=1,seq=x,x为随机生成数值);
2、服务端回复客户端发送的TCP连接请求报文,其中包含seq序列号,是由回复端随机生成的,并且将SYN置为1,而且会产生ACK字段,ACK字段数值是在客户端发送过来的序列号seq的基础上加1进行回复,以便客户端收到信息时,知晓自己的TCP建立请求已得到验证。(SYN=1,ACK=x+1,seq=y,y为随机生成数值)这里的ack加1可以理解为是确认和谁建立连接;
3、客户端收到服务端发送的TCP建立验证请求后,会使自己的序列号加1表示,并且再次回复ACK验证请求,在服务端发过来的seq上加1进行回复。(SYN=1,ACK=y+1,seq=x+1)。
🌸为什么需要第三次通信 ?
-
、在第一次通信过程中,A向B发送信息之后,B收到信息后可以确认自己的收信能力和A的发信能力没有问题。
-
、在第二次通信中,B向A发送信息之后,A可以确认自己的发信能力和B的收信能力没有问题,但是B不知道自己的发信能力到底如何,所以就需要第三次通信。
-
、在第三次通信中,A向B发送信息之后,B就可以确认自己的发信能力没有问题。
1.双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认
2.验证双方的接听发送能力是否正常
🎄四次挥手(断开连接)
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
四次挥手原理
第1次挥手:客户端发送一个FIN,用来关闭客户端到服务端的数据传送,客户端进入FIN_WAIT_1状态;
第2次挥手:服务端收到FIN后,发送一个ACK给客户端,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),服务端进入CLOSE_WAIT状态;
第3次挥手:服务端发送一个FIN,用来关闭服务端到客户端的数据传送,服务端进入LAST_ACK状态;
第4次挥手:客户端收到FIN后,客户端t进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,服务端进入CLOSED状态,完成四次挥手。
其中:FIN标志位数置1,表示断开TCP连接。
四次挥手过程详细说明:
1、客户端发送断开TCP连接请求的报文,其中报文中包含seq序列号,是由发送端随机生成的,并且还将报文中的FIN字段置为1,表示需要断开TCP连接。(FIN=1,seq=x,x由客户端随机生成);
2、服务端会回复客户端发送的TCP断开请求报文,其包含seq序列号,是由回复端随机生成的,而且会产生ACK字段,ACK字段数值是在客户端发过来的seq序列号基础上加1进行回复,以便客户端收到信息时,知晓自己的TCP断开请求已经得到验证。(FIN=1,ACK=x+1,seq=y,y由服务端随机生成);
3、服务端在回复完客户端的TCP断开请求后,不会马上进行TCP连接的断开,服务端会先确保断开前,所有传输到A的数据是否已经传输完毕,一旦确认传输数据完毕,就会将回复报文的FIN字段置1,并且产生随机seq序列号。(FIN=1,ACK=x+1,seq=z,z由服务端随机生成);
4、客户端收到服务端的TCP断开请求后,会回复服务端的断开请求,包含随机生成的seq字段和ACK字段,ACK字段会在服务端的TCP断开请求的seq基础上加1,从而完成服务端请求的验证回复。(FIN=1,ACK=z+1,seq=h,h为客户端随机生成)
至此TCP断开的4次挥手过程完毕。
🌸四次挥手中涉及到的两个重要的状态
- CLOSE_WAIT
出现在被动发起断开连接的一方.
等待关闭(等待调用close方法关闭socket)
注意:对于 CLOSE WAIT,一般而言,对于服务器上出现大量的 CLOSE_WAIT 状态,原因就是服务器没有正确的关闭 socket,导致四次挥手没有正确完成。这是一个 BUG。只需要加上对应的 close 即可解决问题。
- TIME_WAIT
出现在主动发起断开连接的一方.
假设是客户端主动断开连接.
当客户端进入TIME_ WAIT状态的时候,相当于四次挥手已经挥完了.
这里的TIME_WAIT表示当前连接不要立即释放,而是需要等待一会,那为什么需要等待呢?
我们需要注意的是,在四次挥手过程中同样存在丢包,超时重传现象,
-
如果是最后一个ACK丢包了,站在服务器的视角来看,服务器是不知道是因为ACK丢了,还是自己发的FIN丢了,所有统-视为FIN丢了,统一进行重传操作.
-
既然服务器可能要重传FIN,客户端就需要能够针对这个重传的FIN进行ACK响应.很明显,如果刚才彻底把连接释放了,这样的ACK就无法进行了.
-
因此使用TIME_ WAIT状态保留一定的时间, 就是为了能够处理最后-一个ACK丢包的情况,能够在收到重传的FIN之后,进行ACK响应.
这个时间是多长呢?是2MSL
想一想,为什么是TIME_WAIT的时间是2MSL?
-
MSL是TCP报文的最大生存时间,因此TIME_WAIT持续存在2MSL的话
-
就能保证在两个传输方向上的尚未被接收或迟到的报文段都已经消失(否则服务器立刻重启,可能会收到来自上一个进程的迟到的数据,但是这种数据很可能是错误的);
-
同时也是在理论上保证最后一个报文可靠到达(假设最后一个ACK丢失,那么服务器会再重发一个FIN。这时虽然客户端的进程不在了,但是TCP连接还在,仍然可以重发LAST_ACK);
⭕总结
关于《【网络原理】UDP协议的详细解析》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!