TCP是因特网运输层的面向连接的可靠的运输协议

TCP是点对点的,而并不是一个发送方发给一群人。

为了保存验证的消息,例如确认双方信息等。两者需要保存确保数据传输的参数(TCP状态变量)。

客户端先发一个特殊TCP报文,服务器回复一个特殊TCP报文。这两个报文不包含数据

用户发送第三个报文,可以包含要的传输数据。

MSS:最大报文段长度

TCP报文段

image.png

TCP报文由报文头和数据字段组成。MSS限制数据段大小并进行数据包分割。

头部通常有20字节,以32bit作为一个单位。

由源端口16bit,目的端口16bit,序号32bit,确认号32bit,接收窗口16bit,首部长度字段4bit(说明了首部的长度,通常为空),可选变长选项字段(用于协商MSS等),标志字段6bit(ACK,RST,SYN,FIN,CWR,ECE,PSH,URG),紧急数据字段16bit。

序号和确认号

序号用于标识数据流中的每一个字节,使得数据流中的字节保持有序性,每个字节都有唯一的序号。

当MSS为1000时,对于两个1000字节的数据包属于一个数据流,会有序号 0-999 和 1000-1999 。报文段中的序号为该数据流中的第一个序号如上分别是 0 和 1000 。对应的两个包的序号就是 0 和 1000

确认号为发送端期待的下一个数据包的开头序号,对于接受者,收到数据后,将会发送一个确认,其代表 该流中至第一个丢失字节为止的字节,例如收到了0-535则其确认号为536,如果接受了0-200和 300-500,其确认号为201. 这被称为 累计确认

实际操作上,TCP编程人员可以选择丢弃后面这段300-500,轮到的时候再接收一遍,也可以保留,不断获取空缺填充。

Telnet

一个基于TCP远程登陆的应用层协议。其是一个交互式应用。

下图的例子可以很好的解释Seq(序号) 和ACK(确认号)的使用。

image.png

第二个报文段不仅会发送数据给主机A,还确认了主机A传输的数据,代入了确认码,这种确认被称为捎带(piggybacked)。

往返计算

  • SampleRTT:报文样本RTT,发出到被接受的时间段,在某个时刻做一次SampleRTT测量。
  • EstimatedRTT:SampleRTT显然是不稳定的,使用一个为指数加权移动平均(EWMA)来做标准化 EstimatedRTT = (1 - α) • EstimatedRTT + α • SampleRTT(α推荐值0.125)
  • DevRTT:RTT偏差,DevRTT = (1 -β) • DevRTT + β • | SampleRTT - EstimatedRTT |,是SampleRTT与EstimatedRTT之间差值的EWMA(β推荐值0.25)

Timeoutinterval = EstinMrtedRTT +4 • DevRTT

推荐的超时时间,推荐的初始Timeoutinterval为1s,出现超时后将加倍,接受到报文段后就用上述公式重新计算。

可靠数据传输

TCP在ip的服务之上建立了可靠传输服务。涉及到了许多RDT的原理。

对于超时而言,需要定时器,而实际使用的多个计时器成本较高,推荐的定时器管理过程推荐单一的重传定时器。

建立一个假设环境,主机A往主机B传输大文件。

发送方

NextSeqNum=InitialSeqNumber
SendBase=InitialSeqNumber

loop() {
	switch(event)
		事件:从上层应用接受数据
			生成报文段
			if(定时器没有运行)
				启动定时器
			发送报文段
			NextSeqNum=NextSeqNum+length(data)
			break;
		事件:定时器超时
			重传最小序号未应答报文
			启动定时器
			break;
		事件:收到ACK,具有ACK字段值y
			if (y > SendBase) {
				SendBase = y
			}
			if(当前无任何应答报文段){
				启动定时器
			}
			break;
}

发送方有三个事件:从上层应用接受数据,定时器超时,收到ACK

TCP状态变量SendBase是最早未被确认的字节的序号

超时间隔加倍

对于加倍的间隔实现,作为了一个拥塞控制,防止在堵塞的网络中反复重传导致网络中的堵塞会更加验证,TCP经过加倍时间间隔,做到堵塞控制。

快速重传

对于过长的超时周期,导致发送方延迟重传丢失的分组,增加端到端时延。

发送方可在超时前检测丢包,减少延迟。冗余ACK是对已确认报文段的重复确认。

**TCP接收方的ACK生成策略(RFC 5681):**如果接收到的报文段序号大于期望的下一个按序报文段,则说明可能存在丢失。TCP不使用否定确认(NACK),而是通过冗余ACK提示发送方存在丢包。

TCP连接管理

TCP 三次握手

  • 第一步(SYN报文段)

    客户端向服务器发送TCP SYN报文段,不包含应用层数据,SYN标志置1,并随机选择一个初始序号(client_isn)。

  • 第二步(SYNACK报文段)

    服务器收到SYN报文后,分配TCP缓冲和变量,向客户端发送SYNACK报文段,SYN标志置1,确认号设为client_isn + 1,并随机选择服务器的初始序号(server_isn)。

  • 第三步(ACK报文段)

    客户端收到SYNACK后,分配缓冲和变量,并向服务器发送ACK报文段,确认号设为server_isn + 1,SYN标志置0,连接建立,可携带数据。

image.png

TCP 四次挥手

  • 客户端发起关闭连接

    客户端应用进程发送关闭命令,TCP向服务器发送FIN报文段(FIN比特置1)。

  • 服务器确认FIN

    服务器收到FIN报文后,向客户端发送ACK报文段进行确认。

  • 服务器发送FIN

    服务器随后发送自己的FIN报文段(FIN比特置1),表示终止连接。

  • 客户端确认FIN

    客户端收到服务器的FIN报文后,发送ACK报文段进行确认,连接关闭,释放资源。

image.png

关闭状态机

  1. 客户端发起关闭连接
    • 客户端TCP发送FIN报文段(FIN比特置1),进入FIN_WAIT_1状态。
  2. 服务器确认FIN
    • 服务器发送ACK报文段,客户端进入FIN_WAIT_2状态。
  3. 服务器发送FIN
    • 服务器发送FIN报文段(FIN比特置1),客户端收到后发送ACK进行确认,并进入TIME_WAIT状态。
  4. TIME_WAIT阶段
    • 允许客户端重传ACK(若ACK丢失)。
    • 典型等待时间:30秒、1分钟或2分钟。
    • 等待结束后,连接正式关闭,客户端释放所有资源。