TCP/IP 传输控制报文协议
TCP 可靠的流传输服务
概述
传输控制协议,字节流服务
适用于其他不同类型的网络传递服务
可靠传输的特性
1 面向流的服务(比特流、字节流)
2 采用虚电路方式(逻辑连接,面向连接的传输服务)
3 通过缓存技术传输(考虑到传输的效率)
Push机制:设置后不会放在缓存中,数据立即发出(不放到发送缓冲区),直接向应用递交(不放到接收缓冲区)
4 非结构的流(不是以记录为单位的流服务)
5 提供全双工的通信方式,每个方向相对独立(首部有两个序号:发送序号和接收序号)
确认:采用 捎带(piggybacked)技术,把确认放在发给对方的数据报文当中,进行确认。目的是提高传输效率。
提高可靠性的方法
- 带有重传的肯定确认
接收方收到数据时给出肯定确认,发送方对于每一个发送出去的数据报文都启动一个定时器(时钟)来跟踪发送的报文(跟踪对其的确认),一旦超时则重传
超时和重传
接收方收到的报文可能重复,涉及设置超时的间隔的问题。如果超时间隔设置的过小,会产生过早超时问题,带来重复接收的问题。
判定重复方法:在报文首部增加序号字段,每个报文给一个不同的序号,向发送方返回的确认也可以带上序号。
滑动窗口
对比停等:提高带宽的利用率,发送方可以连续发送多个数据报(窗口取值大于1
窗口(未确认的包数)的最大值不能超过序号空间(序号空间的大小,取决于包首部序号值的位数)
如果超过序号空间,则未确认的包中至少有两个包的序号是相同的,接收方无法做区分
分组首部包含kbit的序列号,序号空间为2^k
针对 回退N协议:窗口大小不能超过序号空间
针对 选择重传协议:窗口大小不能超过序号空间大小的一半
接收方也存在一个窗口,与发送方相对应也是一个滑动窗口
TCP协议
TCP标准包含:
- 数据报和确认格式
- 过程可靠
- 区分主机上的多个不同目标
- 差错恢复
- 进行连接的管理(连接的初始化,关闭等)
TCP不包括:
- 没有定义与应用之间的细节
- 对于底层网络没有特殊要求
分层
属于传输层
TCP提供面向连接的虚电路服务(字节流服务
使用TCP服务,多个应用可以进行同时的通信。此处多路复用与解多路复用的依据是端口号
段,流和序列号
- TCP的传输单位:段
- TCP提供一种流的服务,数据流包含在段内进行传输
- TCP段 封装在 IP分组的数据区
需要考虑的问题:
1 如何提高传输效率?
2 如何流量控制?(因特网中不同主机的收发速度、主机间的通信路径负荷等因素)
解决方案:滑动窗口协议
TCP滑动窗口中,窗口的大小在不断变化,接收方需要告诉发送方
通过窗口通告方式:接收方发送确认来告诉发送方(确认包中有一个窗口通告值,表示当前窗口剩余大小)
从而实现流量控制。
在TCP的改进方案中有显示拥塞控制机制。
TCP 段格式
- 传输的数据单位是 段
- 作用:创建连接、传输数据段、进行确认、通告本地窗口大小等
(很多不同类型的段来完成不容类型的功能)
段格式:
- 源端口
- 目的端口
- (seq)序号 32bit:发送序号
- (ack)确认号 32bit:接收序号
- HLEN 4bit:TCP段的首部长度,是以字节为单位
- 保留 6bit
- Code Bits:TCP标志 6bit,表示TCP段的类型
- WINDOW:16bit,向发送方通告本地接收缓冲区的大小
- 报文校验和 16bit
- 紧急指针 16bit -> 联合code bits中urgent标志使用
- 选项 20bit Padding填充
- 数据
Code Bits字段
URG:紧急指针
ACK:确认
PSH:带有PUSH标志的段要求不能进行缓存处理
RST:立即拆除原来建立的一条连接
SYN:创建连接并进行序号的同步(发送方接收方之间建立连接时,选择自己的初始序号并告诉对方
FIN:指双方在传输完毕数据后双方切断连接
Out of Band Data(带外数据)
普通数据的传输占用了一条连接,控制数据优先级高于普通数据,这些控制数据不收流量约束机制的限制
(实际上是TCP中带内数据:可以在普通数据中加入一些控制数据,夹杂在普通数据流里,但是会优先处理)
选项字段
格式:kind(1字节)+ length(1字节)+info(可变字节),长度可变
MSS:最大报文段长度。TCP中最初规定的一种选项,kind=2
MSS告诉对方TCP:本方能接收的报文段的数据字段的最大长度是MSS个字节
MSS与链路层MTU相关
一些其他选项:
- Windows Scale:kind=3,对TCP首部的Window的扩充(针对于网络延迟长但是带宽高的网络,需要提高窗口值)
- TimeStamp:kind=8,时间戳,计算RTT等、当序号到达最大值时翻转为0时提供时间戳可以序号进行大小的判断
- SACK:kind=5,可以进行选择性的确认,通过SACK支出接收块中缺少了哪些
- ……
TCP Checksum字段
算法:将被校验的序列看成16位的整数序列,求这个序列反码和的反码
计算的时候需要使用伪头(与UDP相同)
IPv4的TCP伪首部格式:
与UDP的伪首部的区别在于协议号,TCP报文长度字段不同。
同样,IPv6的TCP伪首部格式:
ACK
- TCP中不以段为单位进行编号,以字节为单位进行编号
1 因为每个段所带的数据长度不一样;在重传时,所带数据比原来的段还要多一些。若以段为单位进行编号,此时就很难去区分数据长度的不同。
2 所以针对字节流,TCP设定字节流起始位置。所以,TCP中的序号是对于数据流中的每个字节编号。 - 确认的序号:所收到段的最后数据字节的序号。在实际给确认值时,还需要在其基础上加一,表示下一次期待的段的号码。
- 积累方式的确认:当前号接收正确,当前号之前的也都接收正确
- 接收对于接收到的段还需要进行重新排序后,再递交给上层的应用
- 接收方给的确认:收到连续字节流中最后那个字节的序号
(如果发送方发送五个段,接收方只接收到了后面四个,那么接收方还是返回第一个段的起始位置。发送方接下来重新发送全部五个段,或者停止发送等待接收方返回的确认。这会造成效率低下的问题。)
超时和重传
TCP每发送一个段就启用一个时钟跟踪,如果超时前时钟确认未收到则重新发送
由于因特网中有很多异构的网络,在这些网络上的网络延迟不相同,所以对超时时间的设置算法需要有自适应的能力
设定超时重传依据RTT
RTT样本采用样本估算方法
采用加权平均方法:
RTT = (aRTT原来的数值)+((1-a) 新的RTT样本)
设置超时时间
Timeout = B * RTT (其中B为大于1的常数)
样本估算
Karn算法
对重传的样本不做统计
但是在初始时都是重传样本,此时RTT就一直得不到调整,那么时钟就可能一直超时产生持续的重传,所以此时采用时钟退避。
时钟的退避
若样本是重传样本,则对Timeout做调整(例如,乘以2)
网络延迟的方差问题
网络延迟的方差指的是网络延迟的变化率。
方差大则出现抖动,使用方差替代常量调整RTT
- RTT的变化
往返延迟的方差与 1/(1-L) 成比例,L是当前网络负载 - 最初TCP标准估算平均RTT的方法
设置 B 为2,此时网络负载最多到达30% - 之后标准采用一个方差来替代 原来的常量B
对超时时钟间隔的设置:
DIFF= SAMPLE- Old RTT
Smoothed RTT= Old RTT + δ DIFF
DEV= Old_DEV +ρ (|DIFF| - Old_DEV)
Timeout = Smoothed RTT + η DEV
DIFF:样本和旧的RTT间的差异
DEV:平均偏差
δ:在0-1之间,对加权平均值Smooth RTT进行控制
ρ:在0-1之间,对偏差DEV进行控制
η:控制平均方差DEV对Timeout的影响
拥塞处理
造成重传,增加延迟,甚至出现拥塞崩溃
解决方案
降低传输速率
(过时)ICMP中source quench报文通知主机出现网络拥塞,让源站减缓发送过程
TCP处理方法 (AIMD)
- 乘法减(muldec):以乘上一个系数的方式来减少,一般情况下减半
接收方窗口大小:在收到报文后返回的确认中通告给发送方
拥塞窗口:在发生拥塞状况的时候引入的窗口值,此时发送方发送的数据要有接收窗口大小和拥塞窗口大小来决定。发送方一般做法是取这两个窗口值的小的。
TCP判断拥塞的方式:检测到丢包情况。
(可能会出现震荡现象) - 慢启动
发送拥塞,将窗口降为1,之后不断增加2的倍数段
如果窗口值到达最初设定的窗口值的一半,此时进入拥塞避免阶段(在所有段的确认都收回时,窗口值加一)
TCP 快速恢复
Fast recovery:快速恢复
如果丢包现象不是经常发生,则可以采用启发式的测略
如果接收方收到三次重复的确认,则启动快速恢复。(此时往往比超时重传快)
快重传不同版本:
Tahoe:
传统的处理,AIMD
Reno:
窗口中丢失了一个报文段的情况
NewReno:
相比Reno处理一个报文的丢失,NewReno可以处理两个报文的丢失。
两个段丢失时,确认返回有两种情况:
1 如果确认在窗口尾部的号码时,表示只丢失了一个段
2 如果确认的序号比丢失的号码大但是比窗口尾部的号码小,表示丢失了第二个段
Vegas:用平均估算RTT的值来替代丢包的情况
TCP显示反馈机制
标准TCP协议中没有显示的拥塞反馈机制
TCP中两个相关的技术:
SACK选项:选择确认
接收方收到发送方发来的不连续的段,SACK选项说明从一个序号到另一个序号的段已经收到了,发送方只重传空缺的数据。ECN:显示拥塞通告,直接显示反馈
采用ECN测略需要修改TCP协议和IP协议
(利用协议首部未定义的字段)
在IP协议首部的TOS字段中,最低的两位被定义成ECN
在TCP协议首部的保留字段中,使用其中的两个bit,一个bit是CWR位:表示发送方的拥塞窗口减少了,另一个bit是ECE位:显示拥塞通告
1 | ECN扩展功能表述 |
拥塞处理策略
中间路由器拥塞的状况
tail-drop:后来的全部丢弃
如果被丢弃的报文段属于一个相同的TCP连接,则发送方进入慢启动状态
如果被丢弃的报文段属于多个不同的TCP连接,则这些连接都进入了慢启动状态,称为:全局同步(此时网络性能大幅降低)
random Early Detection:用于取代tail-drop的策略
系统内设置两个阈值:最小值Tmin和最大值TmaxRED的处理原则:(关键时Tmin,Tmax和概率p的设置)
1 队列长度小于Tmin,则报文加入
2 队列长度超过Tmax,则报文丢弃
3 选择随机以概率p丢弃
TCP连接管理
连接建立和拆除
建立连接
两次握手存在的问题
- 发送方的连接请求可能是重传的,这会进行重复的建立连接
三次握手
1 | - 1 Send: SYN seq = x (x的选择只与site1有关,这是一个初始的序号) |
TCB (传输控制块:一个数据结构)
说明
- 序号的选取问题
双方选取的初始序号,是各自根据本地情况来选取的。
初始号的选取具有一定的随机性,只有在连接的时候会涉及到初始序号的选择问题。
涉及到安全问题:
若第三方非法用户,需要知道通讯双方的初始序号 - 数据的携带问题
一般情况下,seq段不带数据。如果携带数据,这些数据会先缓存起来,直到三次握手成功后才进行发送和接收。一般在通讯中,最后的ACK段会携带数据
关闭连接
正常关闭:gracefully
- 一个方向上的关闭不影响另一个方向的数据流
- 原来缓冲区的缓存数据仍需要发完
- 将段的首部FIN标志置1,对方收到FIN会回复一个确认,收到确认后,两个方向的数据全部断开,总共4次握手(若是3次的情况,则为修改过的断连握手过程)
- 理解成两个方向上的断连
标准的断连过程
1 | - 1 Send: FIN seq = x |
突发式的关闭:
- RST 粗暴的关闭
- 应用:在出口安装一个设备,检测每一个包,检测目标IP是否属于黑名单,是则向用户发送一个RST 断开连接
TCP State Machine
有限状态机
- TIMED WAIT :等待两个段的生命期
在子网中存储起来,突然冒出,则会造成错误接收
1 一方向另一方发送的数据段
2 接收方返回的确认段
强迫数据传输
- 一般将数据存到缓存中等到缓存满时再发送出去,使用Push标志后立即发送
- 实时应用:例如ssh远程连接
TCP性能问题
协议的最大吞吐量:
两个站点在10M的以太网下最大可以到达8M
收发双方应用的速度不一样导致一些性能问题。
SWS:傻窗口综合征
信道利用率几乎为零
避免SWS
Nagle算法:主要是进行缓存的积累
发送方避免:发送方使用缓冲区积累一定长度的数据量
针对不同的应用等待不同的时间
延时时间的处理:
在TCP中通过ACK来触发。在确认到达时缓冲区中积累了一定量的数据。
接收方避免:接收方维持一个本地缓冲区空闲空间大小,区域大小放在确认中反馈给发送方,在反馈的时候进行延迟
(延迟确认的两个条件)—> 最长等待时间
1 缓冲区可用空闲区达到原先缓冲区大小的一半
2 接收缓冲区可用空闲区积累到能够放下一个MSS
二者任意满足其一,接收方就可以将这块空闲的区域通告给发送方。(在实现中包括采用一种零窗口探测来避免死锁)
缓冲区暴涨现象
缓冲区大到一定程度时,缓冲区延迟非常长。无法适用实时应用。
参考资料:
- INTERNETWORKING WITH TCP/IP PRINCIPLES, PROTOCOLS, AND ARCHITECTURE Vol1 (6th Edition). DOUGLASE E. COMER