TCP的三次握手和四次断开

TCP是面向连接的协议,面向连接是指通信双方任何一方向对方发送数据之前必须先建立安全通道,就像打电话一样,必须等到对方的手机响铃,并且对方接听电话时,才能与对方通信。

UDP不是面向连接的协议,基于UDP的通信双方不需要事先与对方协商并建立连接,也不管对方的IP地址和端口号是否存在,就直接发送数据,这个处理方式有点像手机发短信,不管对方手机是否停机或者关机,只管发送信息,不管对方是否能收到消息。

一、在TCP/IP中,采用三次握手来建立一次连接

主机A运行TCP客户程序,主机B运行TCP服务器程序。最初两端的TCP进程都处于CLOSED(关闭)状态。A主动打开连接,B被动打开连接

B的TCP服务器进程首先创建传输控制块TCB,准备接受客户进程的连接请求,然后服务器进程就处于LISTEN(收听)状态,等待客户的连接请求。

1、第一次握手

A的TCP客户进程也是首先创建传输控制模块TCB,然后向B发出连接请求报文段,这时首部中的同步位SYN=1,同时选择一个初始序号seq=x,TCP客户进程A进入SYN-SENT(同步已发送)状态。

2、第二次握手

B收到连接请求报文段之后,如同意连接,则向A发送确认。在确认报文段中应把SYN位和ACK位都置1,确认号为ack=x+1,同时为自己选择一个初始序号seq=y。TCP服务器进程进入SYN-RCVD(同步收到)状态。

3、第三次握手

TCP客户进程A收到B的确认之后,还要向B给出确认,确认报文段的ACK=1,确认号ack=y+1,而自己的序号为seq=x+1,TCP连接建立,A进入established(已建立连接)状态。

扫描二维码关注公众号,回复: 1800996 查看本文章
当B收到A的确认之后,也进入established(已建立连接)状态。


二、TCP为什么需要三次握手,采用两次握手可以吗?

(1)TCP的三次握手过程,主机A向B发送连接请求,主机B对收到的主机A的报文进行确认,主机A再次对主机B的确认进行确认。

(2)采用三次握手是为了防止失效的连接请求报文段突然又传送到主机B,从而产生错误。

A发出连接请求,但因连接请求报文丢失而未收到确认。于是A再重传一次连接请求,后来收到了确认,建立了连接。数据传输完毕之后,就释放了连接。A共发送了两个连接请求报文段,其中第一个丢失,第二个到达了B。

假若出现异常,A发出的第一个连接请求报文段并没有丢失而是在某个网络节点长时间滞留了,以致延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段,但B收到此失效的报文段之后,就误认为是A又发出的一次新的连接请求,于是向A发出确认报文段,同意建立连接。假定不采用三次握手,那么只要B发出确认,新的连接就建立了。

由于A并没有发出建立连接的请求,因此不会理睬B的确认,也不会向B发送数据。但是B却认为新的运输连接已经建立了,并一直等待A发送数据,所以许多资源就被浪费了。

那么采用三次握手的办法就可以防治上述现象的发生。

三、TCP的四次断开

由于TCP连接是全双工的,因此每个方向都必须单独进行关闭当一方数据发送任务完成后就能发送一个FIN来终止这个方向的连接。

(1)客户端发送数据完毕之后,发送一个FIN,提出断开连接请求。

(2)服务器收到该FIN包后,对其作出响应,发送一个ACK包,确认这一方向的连接将关闭。

(3)等服务器的应用程序做好关闭准备时,服务器反方向发送一个FIN包给客户端,请求关闭连接请求。

(4)客户机对服务器发送的请求进行确认,并发送ACK包。

具体过程如下:

数据传输结束后,通信双方都可以释放连接,A和B都处于established状态。

A的应用进程先向其TCP发出连接释放报文段,并停止发送数据,主动关闭TCP连接。A把连接释放报文段首部的终止控制位FIN置1,其序号为seq=u,等于前面已传送过的数据的最后一个字节的序号加1。这时A进入FIN-WAIT-1(终止等待1)状态,等待B的确认。

B收到连接释放报文段后即发出确认,确认号是ack=u+1,而这个报文段自己的序号是v,等于B前面已传送过的数据最后一个字节的序号加1。然后B进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭(half-close)状态,即A已经没有数据要发送了,但是B要发送数据,A仍要接收,也就是从B到A的这个方向的连接并未关闭,这个状态可能会持续一些时间。

A收到B的确认之后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。

若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接,这时B发出的连接释放报文段必须是FIN=1,现假定B的序号为w(在半关闭状态B可能又发送一些数据),B还必须重复上次已发送过的确认号ack=u+1,这时B进入LAST-ACK(最后确认)状态,等待A的确认。

A收到B的连接释放报文段之后,必须对此发出确认,在确认报文段中把ACK置1,确认号ack=w+1,而自己的序号为seq=u+1,然后进入TIME-WAIT(时间等待)状态,现在TCP连接还没有释放掉,必须等到时间等待计时器(TIME-WAIT timer)设置的时间2MSL后,A才进入CLOSED状态。时间MSL叫做最长报文段寿命(Maximum Segment Lifetime),通常建议为2分钟。因此从A进入TIME-WAIT状态后,要经过4分钟才能进入到CLOSED状态,才能建立下一个新的连接。当A撤销相应的传输控制块TCB后,就结束这次的TCP连接。


四、为什么A在TIME-WAIT状态必须等待2MSL的时间?

(1)为了保证A发送的最后一个ACK报文能够到达B,这个ACK报文段有可能丢失,从而使处在LAST-ACK状态的B收不到对已发送的FIN+ACK报文段的确认。B会超时重传这个FIN+ACK报文段,而A就能在2MSL时间内收到这个重传的FIN+ACK报文段。接着A重传一次确认,重新启动2MSL计时器,最后,A、B正常进入CLOSED状态、

如果A在TIME-WAIT状态不等待一段时间,而是在发送完ACK报文段后立即释放连接,那就无法收到B重传的FIN+ACK报文段,因而也不会在发送一次确认报文段,这样,B就无法按照正常步骤进入CLOSED状态。

(2)防止“已失效的连接请求报文段”出现在本链接中。

五、为什么建立连接是三次握手,而关闭连接是四次握手?

服务端的LISTEN状态下的socket收到SYN报文的建立连接请求后,它可以把ACK和SYN放在一个报文里来发送。但是关闭连接时,当收到对方的FIN报文通知时,它仅仅表示对方没有数据发送给你了,但未必你所有的数据都发送给对方了,所以你未必会马上关闭socket,也就是你可能还需要发送一些数据给对方之后,再发送FIN报文给对方来表示同意现在可以关闭连接了,所以这里的ACK和FIN报文多数情况下都是分开发送的。

六、TCP连接的有限状态机

粗实线箭头表示对客户进程的变迁,粗虚线表示服务器进程,细线箭头表示异常变迁。


猜你喜欢

转载自blog.csdn.net/qq_32164245/article/details/80618107