玩命加载中 . . .

5.2-TCP(下)


TCP报文段格式

  • 源端口:占16比特,写入源端口号,用来标识发送该TCP报文段的应用进程
  • 目的端口:占16比特,写入目的端口号,用来标识接收该TCP报文段的应用进程
  • 序号:占32比特,取值范围$[0, 2^{32}-1]$,序号增加到最后一个后,下一个序号就又回到0。TCP报文段的数据载荷中的每个字节都有序号,首部中的序号是TCP报文段数据载荷的第一个字节的序号
  • 确认号:占32比特,取值范围$[0, 2^{32}-1]$,确认号增加到最后一个后,下一个确认号就又回到0。指出期望收到对方下一个TCP报文段的数据载荷的第一个字节的序号,同时也是对之前收到的所有数据的确认
  • 确认标志位ACK:取值为1时确认号字段才有效,取值为0时确认号字段无效。TCP规定,在连接建立后所有传送的TCP报文段都必须把ACK置1
  • 同步标志位SYN:在TCP连接建立时用来同步序号
  • 终止标志位FIN:用来释放TCP连接
  • 复位标志位RST:用来复位TCP连接,当RST=1时,表明TCP连接出现了异常,必须释放连接,然后再建立连接。RST置1还用来拒绝一个非法的报文段或拒绝一个TCP连接
  • 推送标志位PSH:接收方的TCP收到该标志位为1的报文段会尽快上交应用程序,而不必等到接收缓存都填满再向上交付
  • 紧急标志位URG:取值为1时紧急指针字段有效
  • 紧急指针:占16比特,以字节为单位,用来指明紧急数据的长度。当发送方有紧急数据时,可将紧急数据插队到发送缓存的最前面,并立刻封装成TCP报文段进行发送。紧急指针会指出本报文段数据载荷部分包含多长的紧急数据,紧急数据之后是普通数据。接收方收到紧急指针为1的报文段,会按照紧急指针字段的值,从数据载荷部分取出紧急数据,并直接上交应用进程,而不必在接收缓存中排队
  • 首部长度:占4比特,并以4字节为单位用来指出TCP报文段的首部长度,首部固定长度20字节,因此首部长度字段的最小值为$(0101)_2$,首部最大长度为60字节,因此首部长度字段的最大值为$(1111)_2$
  • 保留:占6比特,保留为今后使用,目前应置为0
  • 窗口:占16比特,以字节为单位。指出发送本报文段的一方的接收窗口,窗口值作为接收方让发送方设置其发送窗口的依据,这是以接收方的接收能力来控制发送方的发送能力,称为流量控制
  • 校验和:占16比特,检查范围包括TCP报文段的首部和数据载荷两部分

TCP报文段除了20字节的固定部分,还有最大40字节的选项部分,目前有以下选项:

  • 最大报文段长度MSS:TCP报文段数据载荷部分的最大长度
  • 窗口扩大选项
  • 时间戳选项
  • 选择确认选项

填充字段:由于选项的长度可变,因此使用填充来确保报文段首部能被4整除,因为首部长度字段是以4字节为单位的

TCP三次握手

最初,客户端和服务器端的TCP进程都处于关闭状态,一开始,TCP服务器进程首先创建传输控制块,之后进入监听状态,等待客户端的连接请求

TCP客户端进程也是首先创建传输控制块,然后在打算建立TCP连接时,向服务器进程发送连接请求报文段,并进入同步已发送状态SYN_SENT,连接请求报文段首部中的SYN被设置为1,序号字段seq设置一个初始值x,作为TCP客户端进程所选择的初始序号

TCP规定SYN被设置为1的报文段不能携带数据,但要消耗掉一个序号

服务器进程收到连接请求报文段后,就向客户进程发送TCP连接请求的确认报文段,并进入同步已接收状态SYN_RCVD,该报文段首部中的同步位SYN和确认位ACK都设置为1,序号字段seq设置为初始值y,作为TCP服务器进程所选择的初始序号,确认号字段ack设置为x+1,这个报文段也不能携带数据

TCP客户进程收到确认报文段后,还要回一个普通的确认报文段,并进入连接已建立状态ESTABLISHED,将确认位ACK设置为1,序号字段seq设置为x+1,这是因为客户进程发送的第一个报文段的序号为x,并且不携带数据,因此第二个报文段的序号为x+1,确认字段ack被设置为y+1,这是对服务器进程所选择的初始序号的确认,服务器进程收到该报文后也进入连接已建立状态ESTABLISHED,现在,双方都进入了连接已建立状态,可以进行数据传输了

采用“三次握手”而不是“两次握手”建立TCP连接,是为了防止已失效的连接请求报文段突然又传到了服务器,因而导致错误

TCP四次挥手

TCP客户进程会发送连接释放报文段,并进入终止等待1FIN_WAIT_1状态,该报文段首部中的终止位FIN和确认位ACK被设置为1,表明这是一个TCP连接释放报文段,同时也对之前收到的报文段进行确认,序号seq字段设置为u,等于客户进程之前已发送过的数据的最后一个字节的序号加1,确认号ack设置为v

TCP服务器进程收到连接释放报文段后,会发送一个普通的确认报文段,并进入关闭等待状态CLOSE_WAITACK设置为1,序号seq设置为v,确认号ack设置为u+1,这是对客户端发送的连接释放报文段的确认。此时,客户端到服务端的方向的连接就释放了,这时的TCP连接处于半关闭状态,也就是客户端没有数据要发送了,但服务器如果还有数据要发送,客户端依然要接收

客户端收到确认报文段就进入终止等待2FIN_WAIT_2状态

如果服务器也没有数据要发送了,就发送连接释放报文段并进入最后确认状态LAST_ACK,该报文段首部中的终止位FIN和确认位ACK都设置为1,假定序号seq字段的值为w,确认号ack的值为u+1,这是对之前收到的连接释放报文段的重复确认

客户端收到连接释放报文段后,发送普通的确认报文段,然后进入时间等待状态TIME_WAIT,该报文段首部中的确认位ACK设置为1,序号seq的值为u+1,确认号ack的值为w+1

服务器收到确认报文段后就进入关闭状态

而客户端要进过2MSL(Maximum Segment Lifetime)后才能进入关闭状态

如果客户端发送完确认报文段后就直接进入关闭状态,该报文段可能在传输过程中丢失了,这会导致服务器端的连接释放报文段的超时重传,但此时客户端已经处于关闭状态,因此不理会该报文段,这会导致TCP服务器反复重传连接释放报文段,并一直处于最后确认状态而无法进入关闭状态

因此,时间等待状态以及处于该状态2MSL时长,可以确保服务器可以收到最后一个确认报文段而进入关闭状态

另外,客户端发送完最后一个确认报文段后,再经过2MSL时长,就可以使本次连接持续时间内所产生的所有报文段都从网络中消失,这样就可以使下一个新的连接中不会出现旧连接中的报文段


文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录