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 段格式

  • 传输的数据单位是 段
  • 作用:创建连接、传输数据段、进行确认、通告本地窗口大小等
    (很多不同类型的段来完成不容类型的功能)

段格式:

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伪首部格式:

    IPv4 TCP伪首部格式

    与UDP的伪首部的区别在于协议号,TCP报文长度字段不同。

    同样,IPv6的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
2
ECN扩展功能表述
主机A向主机B发送报文。在中间路径的路由器上发生拥塞。IP分组达路由器后,路由器将分组首部的TOS字段中的ECN两位都置为1,然后转发出去。在主机B收到这个报文后,发现链路上发生拥塞,此时向主机A返回的确认报文中首部的ECE位置为1,通知主机A发生网络拥塞。主机A在收到主机B发来的确认包后,将自己的拥塞窗口减半。将接下来要发出去给B的TCP数据段首部中的CWR置为1表示要将拥塞窗口减半。

拥塞处理策略

中间路由器拥塞的状况

  • tail-drop:后来的全部丢弃

    如果被丢弃的报文段属于一个相同的TCP连接,则发送方进入慢启动状态

    如果被丢弃的报文段属于多个不同的TCP连接,则这些连接都进入了慢启动状态,称为:全局同步(此时网络性能大幅降低)

  • random Early Detection:用于取代tail-drop的策略
    系统内设置两个阈值:最小值Tmin和最大值Tmax

    RED的处理原则:(关键时Tmin,Tmax和概率p的设置)

    1 队列长度小于Tmin,则报文加入
    2 队列长度超过Tmax,则报文丢弃
    3 选择随机以概率p丢弃

TCP连接管理

连接建立和拆除

建立连接

两次握手存在的问题

  • 发送方的连接请求可能是重传的,这会进行重复的建立连接

三次握手

三次握手

1
2
3
4
- 1  Send: SYN seq = x							(x的选择只与site1有关,这是一个初始的序号)
- 2 Recv: SYN Send: SYN seq = y, ACK x+1 (y的选择只与site2有关,假设将SYN标志看成1个字节的数据)
- 3 Recv: SYN, ACK Send: ACK y+1
- 4 ACK

TCB (传输控制块:一个数据结构)

说明

  • 序号的选取问题
    双方选取的初始序号,是各自根据本地情况来选取的。
    初始号的选取具有一定的随机性,只有在连接的时候会涉及到初始序号的选择问题。
    涉及到安全问题:
    若第三方非法用户,需要知道通讯双方的初始序号
  • 数据的携带问题
    一般情况下,seq段不带数据。如果携带数据,这些数据会先缓存起来,直到三次握手成功后才进行发送和接收。一般在通讯中,最后的ACK段会携带数据

关闭连接

正常关闭:gracefully

  • 一个方向上的关闭不影响另一个方向的数据流
  • 原来缓冲区的缓存数据仍需要发完
  • 将段的首部FIN标志置1,对方收到FIN会回复一个确认,收到确认后,两个方向的数据全部断开,总共4次握手(若是3次的情况,则为修改过的断连握手过程)
  • 理解成两个方向上的断连

标准的断连过程

4次挥手

1
2
3
4
5
6
7
8
9
- 1  Send: FIN seq = x
- 2 Recv: FIN Send : ACK x+1 (FIN标志在协议中也算作一个字节)
- 3 Recv: ACK

- 3 Send: FIN seq = y ACK x+1
- 4 Recv: FIN, ACK Send: ACK y+1
- 5 Recv: ACK

// 若3次,则两个3操作合并为一次操作(site1断连的时候恰好site2中没有数据在发送)

突发式的关闭:

  • RST 粗暴的关闭
  • 应用:在出口安装一个设备,检测每一个包,检测目标IP是否属于黑名单,是则向用户发送一个RST 断开连接

TCP State Machine

有限状态机

TCP有限状态机

  • 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