运输层8——TCP运输连接管理
写在前面:本文章是针对《计算机网络第七版》的学习笔记
TCP是面向连接的协议。运输连接有三个阶段:建立连接、数据传输以及释放连接。TCP连接的建立采用客户服务器的方式。主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器。
TCP建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个TCP报文段,也叫三报文握手。
如图:
-
假定A是客户,B是服务器,最初TCP的两端都是关闭状态,然后A主动打开,B被动打开;
-
一开始,B的TCP服务器先创建传输控制块TCB,准备接受客户进程的连接请求。然后服务就处于LISTEN状态,等待客户的连接请求;
-
A也是先创建TCB模块,在打算建立TCP连接时,向B发送连接请求报文段,这时首部同步位SYN=1,同时选择一个初始序号seq=x。TCP规定,SYN报文段不携带数据但是要消耗一个序号,这时客户进程进入到SYN-SENT(同步已发送)的状态;
-
B收到A的连接请求报文段后,如果同意建立连接,则向A发送确认。设置SYN=1,ACK=1,确认号ack=x+1,并且设置初始序号seq=y。这个报文段也不携带数据但是消耗一个序号。这时TCP服务器进入到SYN-RCVD(同步收到)的状态;
-
TCP客户进程收到B的确认后,还要向B发送确认。ACK=1,seq=x+1,ack=y+1。此时的ACK报文段可以携带数据,但如果不携带数据则不消耗序号下一个报文段的序号仍是seq=x+1。此时TCP连接已经建立,并且客户进程进入到ESTABLISHED(连接已建立)的状态;
-
B收到A的确认后,也进入到ESTABLISHED的状态。
为什么A还要发送最后一次确认呢?
这是防止已失效的连接请求报文段突然又传送到了B而引发错误。
失效的连接请求:A第一次先发送了一个请求,但是丢失了,于是A再发送一个连接请求,重新建立连接,发送数据并释放连接。
但是有可能出现异常情况,即A发送的连接请求并没有丢失,而是滞留了在网络中。如果在传输数据完成之后,这个请求又发到B,B误以为A还要发送数据,因此发送确认报文,但是A没有运输需求,因此不予理睬。如果没有最后一次确认,B一直等待A的确认,这样会造成的浪费。
采用三报文握手,如果B没有收到A的确认,则可以知道A没有建立连接的需求,就可以避免上述这种情况。
2. TCP的连接释放
如图:
-
A和B目前都处于ESTABLISHED状态,A的应用进程向其TCP发出连接释放报文段,并停止发送数据,主动关闭TCP连接。此时,FIN=1,seq=u,u等于前面已发送的最后一个字节的序号加1。这时A进入到FIN-WAIT-1(终止等待1)状态,等待B的确认。FIN报文段即使不携带数据,也要消耗一个序号;
-
B收到释放连接后立即发出确认,此时,ACK=1,确认号是ack=u+1,序号seq=v,v等于B前面所有已传送数据的最后一个字节的序号加1。B进入到CLOSE-WAIT(关闭等待)状态,TCP服务器进程向高层应用进程告知,此时A到B的连接已经释放,TCP连接处于半关闭状态。但是,B到A这个方向的连接尚未关闭;
-
A收到B的确认后,就进入到FIN-WAIT2(终止等待2)的状态,等待B发送连接释放报文段;
-
若B已经没有数据需要发送,则应用进程通知TCP释放连接,这时B发送的报文段:FIN=1,ACK=1,seq=w(可能后面又发送了一些数据),ack=u+1,并且这个报文消耗一个序号。B进入到LAST-ACK(最后确认)的状态,等待A的确认;
-
A收到B的确认后,必须对此发送确认报文。该报文中:ACK=1,seq=u+1,ack=w+1。然后进入到TIME-WAIT(时间等待)状态。
-
此时TCP连接并没有完全释放,必须经过时间等待计时器设置的时间2MSL之后,A才进入CLOSED状态。时间MSL叫做最大报文段寿命。
那么,为什么要等待2MSL的时间呢?
-
保证A最后发送的ACK报文段能够到达B。因为这个报文可能丢失,因此B会重传最后一个确认报文段,A再重新发送确认报文,并且重启计时器,直到A,B都能正常进入到CLOSED状态;
-
防止上面提到的“已失效的连接请求报文”。这段时间内,这些连接请求报文就可能在网络中消失。
此外,B要比A先进入CLOSED状态。