TCP是因特网运输层的面向连接的可靠的运输协议
TCP是点对点的,而并不是一个发送方发给一群人。
为了保存验证的消息,例如确认双方信息等。两者需要保存确保数据传输的参数(TCP状态变量)。
客户端先发一个特殊TCP报文,服务器回复一个特殊TCP报文。这两个报文不包含数据
用户发送第三个报文,可以包含要的传输数据。
MSS:最大报文段长度
TCP报文段
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(确认号)的使用。
第二个报文段不仅会发送数据给主机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,连接建立,可携带数据。
TCP 四次挥手
-
客户端发起关闭连接
客户端应用进程发送关闭命令,TCP向服务器发送FIN报文段(FIN比特置1)。
-
服务器确认FIN
服务器收到FIN报文后,向客户端发送ACK报文段进行确认。
-
服务器发送FIN
服务器随后发送自己的FIN报文段(FIN比特置1),表示终止连接。
-
客户端确认FIN
客户端收到服务器的FIN报文后,发送ACK报文段进行确认,连接关闭,释放资源。
关闭状态机
- 客户端发起关闭连接
- 客户端TCP发送FIN报文段(FIN比特置1),进入FIN_WAIT_1状态。
- 服务器确认FIN
- 服务器发送ACK报文段,客户端进入FIN_WAIT_2状态。
- 服务器发送FIN
- 服务器发送FIN报文段(FIN比特置1),客户端收到后发送ACK进行确认,并进入TIME_WAIT状态。
- TIME_WAIT阶段
- 允许客户端重传ACK(若ACK丢失)。
- 典型等待时间:30秒、1分钟或2分钟。
- 等待结束后,连接正式关闭,客户端释放所有资源。