写在前面:本文章是针对《计算机网络第七版》的学习笔记

运输层1——运输层协议概述

运输层2——用户数据报协议UDP

运输层3——传输控制协议TCP概述

运输层4——TCP可靠运输的工作原理

运输层5——TCP报文段的首部格式

运输层6——TCP可靠传输的实现

运输层7——TCP的流量控制和拥塞控制

运输层8——TCP运输连接管理

TCP是面向连接的协议。运输连接有三个阶段:建立连接、数据传输以及释放连接。TCP连接的建立采用客户服务器的方式。主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器。

1. TCP的连接建立

TCP建立连接的过程叫做握手,握手需要在客户和服务器之间交换三个TCP报文段,也叫三报文握手。

5d36b730af99d71230

如图:

  • 假定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的连接释放

5d36c06f25e4685687

如图:

  • 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的时间呢?

  1. 保证A最后发送的ACK报文段能够到达B。因为这个报文可能丢失,因此B会重传最后一个确认报文段,A再重新发送确认报文,并且重启计时器,直到A,B都能正常进入到CLOSED状态;

  2. 防止上面提到的“已失效的连接请求报文”。这段时间内,这些连接请求报文就可能在网络中消失。

此外,B要比A先进入CLOSED状态。