TCP连接的建立和释放(三次握手和四次挥手)

来源:互联网 发布:港台电视直播软件app 编辑:程序博客网 时间:2024/05/21 01:57
TCP的连接建立

TCP的连接建立也称握手,握手需要在客户机与服务器之间交换三个TCP报文段,下图给出了三次握手建立连接的过程。


连接建立的详细过程:
第一次握手 A向B发送连接请求报文段,这时连接请求报文段的首部同部位SYN=1,同时选择是一个初始序号seq=x。(TCP规定SYN=1的报文不能携带数据,但是需要消耗一个序号),这时,A的TCP客户进程进入SYN-SENT(同步已发送状态)。
第二次握手 B收到A的连接请求报文段之后,如果同意建立连接,则向A发送确认。此时确认报文中,ACK=1(对报文的确认),SYN=1,确认号ack=x+1,还要为自己选择一个初始序号seq=y。注意,此报文不能携带数据,但是需要消耗一个序号。此时,B的TCP服务器进程进入到SYN-RCVD(同步收到状态)。
第三次握手 A收到B的确认之后,还要向B给出确认。此时确认报文中,ACK=1,ack=y+1, seq=x+1。注意,ACK报文可携带数据,如果不携带数据则不消耗序号。此时,对A来说TCP连接已经建立,A进入ESTABLISHED(已建立连接状态)。
当B收到A的确认后,也进入ESTABLISHED状态,连接被真正的建立起来。

为什么是三次握手?
有人认为两次握手就可以成功建立起连接状态,其实两次握手是不稳定的,或者说容易出现错误。
有一种情况,A发出的连接请求报文在某些网络结点被长时间滞留,A进行了一次重传连接请求,这次成功与B建立起连接,并且在数据传输完成之后成功释放连接。这时A第一次的连接请求到达了B,这个报文本来应该作废,但是B以为A要再次建立连接,于是B向A发送确认报文,同意A的连接请求。如果是两次握手,在这时B认为连接已经建立。而A并没有发出建立连接的请求,所以不会理会B的确认,也不会向B发送数据,但是B认为连接已建立,就一直等待A发送数据,导致资源的浪费。


TCP的连接释放
TCP的连接释放也称挥手,挥手需要在客户机与服务器之间交换四个TCP报文段,下图给出了四次挥手释放连接的过程。

连接释放的详细过程:
第一次挥手 A向B发送连接释放报文,此时报文首部FIN=1,其序号seq=u(u等于前面已传送数据的最后一个字节的序号+1),此时A进入FIN-WAIT-1(终止等待1状态)。等待B的确认。注意,TCP规定,即使FIN报文段不携带数据,也会消耗一个序号。
第二次挥手 B收到连接释放报文时会发出确认,此时确认报文首部ACK=1,ack=u+1,seq=v(v等于前面已传送数据的最后一个字节的序号+1),此时B进入CLOSE-WAIT(关闭等待状态)
在第二次挥手成功后,A会进入到FIN-WAIT-2(终止等待2状态),这时A->B的连接已经关闭,但是B->A的连接还没有关闭,此时的状态称为半关闭状态。
第三次挥手 如果B没有数据发送给A,此时B就应该释放连接,B会发送连接释放报文,此时报文首部FIN=1,确认号ack=u+1(A->B的连接被释放,A不可能在发送数据到B,所以确认号不变),B的序号seq=w(在半关闭状态B可能向A发送了数据,会导致B的序号改变)。此时B进入LAST-ACK(最后确认状态),等待A的确认。
第四次挥手 A在收到B的连接释放请求后必须确认,此时确认报文首部ACK=1,ack=w+1,seq=u+1,此时A进入到TIME-WAIT(时间等待状态)。注意,此时TCP连接没有释放掉。必须等到时间等待计数器设置的时间2MSL(MSL为最长报文寿命)后,A才会进入到CLOSED状态。B收到A的确认后就会进入到CLOSED状态。此时A和B之间的连接被完全释放。

为什么A会进入TIME-WAIT状态等待2MSL后,才进入到CLOSED状态?
第一:为了保证A发送的最后一个ACK报文被B接收到。这个ACK报文可能丢失,B会收不到A的确认,B会进行超时重传B->A的连接释放报文。A收到后会重新进行确认,这时A会重启2MSL计数器。这样做可以保证A和B最后都进入到正常的CLOSED状态。
第二:为了防止“已失效的连接请求报文段”出现在本链接中。A在发送完成最后的ACK报文后,进行等待,会使本链接持续的时间内所产生的所有报文从网络中消失。

为什么要四次挥手?
TCP是全双工模式,这就意味着,当A发出FIN报文段时,只是表示A已经没有数据要发送了,A告诉B,它的数据已经全部发送完毕了,A要断开A->B的单向连接;但是,这个时候A还是可以接受来自B的数据,当B返回ACK报文段时,表示它已经知道A没有数据发送了,但是B还是可以发送数据到A的;当B也发送了FIN报文段时,这个时候就表示B也没有数据要发送了,就会告诉A,我也没有数据要发送了,这时B要断开B->A的单项连接,当这条连接也被释放,那么连接就真正的释放掉了。

阅读全文
0 0