TCP协议三次握手与四次挥手详解

时间:2023-03-08 17:35:49

在计算机网络的学习中TCPi协议与Http协议是我们必须掌握的内容,其中Tcp协议属于传输层,而Http协议属于应用层,本博客主要讲解Tcp协议中的三次握手与四次挥手,关于Http协议感兴趣的可以参看我的博客:HTTP协议详解

一.三次握手:

第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,进入SYN_SEND状态,等待服务器确认; 

第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器 进入SYN_RECV状态; 

第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入 ESTABLISHED状态,完成三次握手。 

通过这样的三次握手,客户端与服务端建立起可靠的双工的连接,开始传送数据。 

三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。

用图示表示如下:

TCP协议三次握手与四次挥手详解

那么为何需要三次握手呢?为何不是两次,即客户端给服务器端发送请求,服务器端应答请求做出回应。

最本质的原因是网络是一个复杂的环境,很可能存在网络环境较差的情况,即网络中可能存在某些信息滞留的情况,需要第三次握手(即客户端还要对服务器端的同步包做出确认才能建立连接)是为了防止已失效的连接请求报文段突然又传到了服务器端。现在我们考虑两种情况:

已失效的报文段:

第一种情况:已失效的报文段丢失了:A发出连接请求,但因为丢失了,故而不能收到B的确认。于是A重新发出请求,然后收到确认,建立连接,数据传输完毕后,释放连接,A发了2个,一个丢掉,一个到达,没有“已失效的报文段”

第二种情况:已失效的报文段没丢失,仅仅在网络中某个节点滞留了,延误到达,本来这是一个早已失效的报文段,但是在A发送第二个,并且得到B的回应,建立了连接以后,这个报文段竟然到达了,于是B就认为,A又发送了一个新的请求,于是发送确认报文段,同意建立连接,假若没有三次的握手,那么这个连接就建立起来了(有一个请求和一个回应),此时,A收到B的确认,但A知道自己并没有发送建立连接的请求,因为不会理睬B的这个确认,于是呢,A也不会发送任何数据,而B呢却以为新的连接建立了起来,一直等待A发送数据给自己,此时B的资源就被白白浪费了。但是采用三次握手的话,A就不发送确认,那么B由于收不到确认,也就知道并没有要求建立连接。

二.四次挥手

本质上是两个二次挥手过程。用图示表示如下:

TCP协议三次握手与四次挥手详解

FIN_WAIT_1::这个是已经建立连接之后,其中一方(通常为客户端)请求终止连接,等待对方的FIN报文。

FIN_WAIT-2状态:这就是著名的半关闭的状态了,服务器端收到连接释放报文段后就立即发送确认,然后就进入close-wait状态,当客户端收到服务器端的确认后就进入FIN_WAIT-2状态。这是在关闭连接时,客户端和服务器两次握手之后的状态。此时从客户端到服务器端的连接就释放了。即“半关闭”状态。即客户端不可以发送信息给服务器端,但是服务器端可以发送给客户端,即此时客户端只能接受数据,这也很好理解因为是客户端请求与服务器端断开连接,所以从客户端到服务器端的连接被释放。

此时,若服务器端没有数据报要发送给客户端了,其应用进程就通知TCP释放连接,然后发送给客户端连接释放报文段,此时服务器端等待确认进入LAST_ACK状态,该状态是为了等待对方的ACK报文,当收到ACK报文后,也即可以进入到CLOSED可用状态了



客户端发送确认后,进入time-wait,注意,此时TCP连接还没有释放掉,然后经过时间等待计时器设置的2MSL后,客户端才进入到close状态。

为什么要等待呢?

①、为了保证客户端发送的最后一个ACK报文段能够到达服务器端。即最后这个确认报文段很有可能丢失,那么B会超时重传,然后客户端再一次确认,同时启动2MSL计时器,如此下去。如果没有等待时间,发送完确认报文段就立即释放连接的话,服务器端就无法重传了(连接已被释放,任何数据都不能出传了),因而也就收不到确认,就无法按照步骤进入CLOSE状态,即必须收到确认才能close。

②、防止“已失效的连接请求报文段”出现在连接中。经过2MSL(报文段最大生存时间MSL(maximum segment lifetime)),那些在这个连接持续的时间内,产生的所有报文段就可以都从网络中消失。即在这个连接释放的过程中会有一些无效的报文段滞留在楼阁结点,但是呢,经过2MSL这些无效报文段就肯定可以发送到目的地,不会滞留在网络中。这样的话,在下一个连接中就不会出现上一个连接遗留下来的请求报文段了。

可以看出:服务器端结束TCP连接的时间比客户端早一点,因为服务器端收到确认就断开连接了,而客户端还得等待2MSL.