三、传输层,《计算机网络(自顶向下方法 第7版,James F.Kurose,Keith W.Ross)》

文章目录

    • 一、概述和传输层服务
      • [1.1 传输服务和协议](#1.1 传输服务和协议)
      • [1.2 传输层 vs 网络层](#1.2 传输层 vs 网络层)
      • [1.3 Internet 传输层协议](#1.3 Internet 传输层协议)
    • 二、多路复用与解复用
      • [2.1 多路复用](#2.1 多路复用)
      • [2.2 多路复用解复用工作原理](#2.2 多路复用解复用工作原理)
      • [2.3 无连接(UDP)多路解复用](#2.3 无连接(UDP)多路解复用)
        • [2.3.1 无连接多路解复用例子](#2.3.1 无连接多路解复用例子)
      • [2.4 面向连接(TCP)的多路复用](#2.4 面向连接(TCP)的多路复用)
        • [2.4.1 面向连接的解复用:例子](#2.4.1 面向连接的解复用:例子)
        • [2.4.2 面向连接的多路复用:多线程Web Server](#2.4.2 面向连接的多路复用:多线程Web Server)
    • 三、无连接传输:UDP
      • [3.1 UDP:用户数据报协议](#3.1 UDP:用户数据报协议)
      • [3.2 UDP校验和](#3.2 UDP校验和)
    • 四、可靠数据传输(rdt)的原理
      • [4.1 可靠数据传输:问题描述](#4.1 可靠数据传输:问题描述)
        • [4.1.1 Rdt1.0:在可靠信道上的可靠数据传输](#4.1.1 Rdt1.0:在可靠信道上的可靠数据传输)
        • [4.1.2 Rdt2.0:具有比特差错的信道](#4.1.2 Rdt2.0:具有比特差错的信道)
        • [4.1.3 Rdt2.1](#4.1.3 Rdt2.1)
        • [4.1.4 Rdt2.2:无NAK的协议](#4.1.4 Rdt2.2:无NAK的协议)
        • [4.1.5 Rdt3.0:具有比特差错和分组丢失的信道](#4.1.5 Rdt3.0:具有比特差错和分组丢失的信道)
        • [4.1.6 流水线:提高链路利用率](#4.1.6 流水线:提高链路利用率)
      • [4.2 通用:滑动窗口(slide window)协议](#4.2 通用:滑动窗口(slide window)协议)
        • [4.2.1 发送窗口滑动过程------相对表示法](#4.2.1 发送窗口滑动过程——相对表示法)
        • [4.2.2 滑动窗口(slide window)协议](#4.2.2 滑动窗口(slide window)协议)
          • [4.2.2.1 发送窗口(sending window)](#4.2.2.1 发送窗口(sending window))
          • [4.2.2.2 接收窗口(receving window)](#4.2.2.2 接收窗口(receving window))
        • [4.2.3 正常情况下两个窗口间的互动](#4.2.3 正常情况下两个窗口间的互动)
        • [4.2.4 异常情况下GBN的2窗口互动](#4.2.4 异常情况下GBN的2窗口互动)
        • [4.2.5 异常情况下SR的2窗口互动](#4.2.5 异常情况下SR的2窗口互动)
        • [4.2.6 GBN协议和SR协议的异同](#4.2.6 GBN协议和SR协议的异同)
        • [4.2.7 流水线协议:总结](#4.2.7 流水线协议:总结)
        • [4.2.8 思考题:窗口的最大尺寸](#4.2.8 思考题:窗口的最大尺寸)
    • 五、面向连接的传输:TCP
      • [5.1 概述](#5.1 概述)
      • [5.2 TCP 报文段结构](#5.2 TCP 报文段结构)
      • [5.3 可靠数据传输](#5.3 可靠数据传输)
        • [5.3.1 TCP发送方(简化版)](#5.3.1 TCP发送方(简化版))
        • [5.3.2 TCP 发送方事件:](#5.3.2 TCP 发送方事件:)
        • [5.3.3 TCP:重传](#5.3.3 TCP:重传)
        • [5.3.4 产生TCP-ACK的建议](#5.3.4 产生TCP-ACK的建议)
        • [5.3.5 快速重传](#5.3.5 快速重传)
      • [5.4 流量控制](#5.4 流量控制)
      • [5.5 连接管理](#5.5 连接管理)
        • [5.5.1 同意建立连接](#5.5.1 同意建立连接)
        • [5.5.2 TCP 3次握手](#5.5.2 TCP 3次握手)
        • [5.5.3 关闭连接](#5.5.3 关闭连接)
    • 六、拥塞控制原理
      • [6.1 拥塞的原因/代价:场景1](#6.1 拥塞的原因/代价:场景1)
      • [6.2 拥塞的原因/代价:场景2](#6.2 拥塞的原因/代价:场景2)
      • [6.3 拥塞的原因/代价:场景3](#6.3 拥塞的原因/代价:场景3)
      • [6.4 拥塞控制方法](#6.4 拥塞控制方法)
        • [6.4.1 案例学习: ATM ABR 拥塞控制](#6.4.1 案例学习: ATM ABR 拥塞控制)
    • [七、TCP 拥塞控制](#七、TCP 拥塞控制)
      • [7.1 机制](#7.1 机制)
      • [7.2 拥塞感知](#7.2 拥塞感知)
      • [7.3 速率控制方法](#7.3 速率控制方法)
      • [7.4 TCP拥塞控制和流量控制的联合动作](#7.4 TCP拥塞控制和流量控制的联合动作)
        • [7.4.1 策略概述](#7.4.1 策略概述)
        • [7.4.2 TCP慢启动](#7.4.2 TCP慢启动)
        • [7.4.3 AIMD(Additive- Increase, Multiplicative- Decrease)](#7.4.3 AIMD(Additive- Increase, Multiplicative- Decrease))
        • [7.4.4 改进](#7.4.4 改进)
      • [7.5 总结](#7.5 总结)
      • [7.6 TCP吞吐量](#7.6 TCP吞吐量)
      • [7.7 TCP公平性](#7.7 TCP公平性)
    • 八、总结

一、概述和传输层服务

1.1 传输服务和协议

  • 为运行在不同主机上的应 用进程提供逻辑通信
  • 传输协议运行在端系统
    • 发送方:将应用层的报文分成报文段,然后传输给网络层
    • 接收方: 将报文段重组成报文,然后传递给应用层
  • 有多个传输层协议可供应选择
    • Internet:TCP 和 UDP

1.2 传输层 vs 网络层

  • 网络层服务:主机之间的逻辑通信
  • 传输层服务 :进程间的逻辑通信
    • 依赖于网络层的服务
      • 延时、阻塞
    • 并对网络层的服务进行加强
      • 数据丢失、顺序混乱、加密

有些服务是可以加强的:不可靠 -> 可靠;安全 但有些服务是不可以被加强的:带宽,延迟

类比:东西2个家庭的通信

Ann家的12个小孩给另Bi家的12个小孩发信

  • 主机 = 家庭
  • 进程 = 小孩
  • 应用层报文 = 信封中的信件
  • 传输协议 = Ann 和 Bill
    • 为家庭小孩提供复用解复用服务
  • 网络层协议 = 邮政服务
    • 家庭-家庭的邮包传输服务

1.3 Internet 传输层协议

  • 可靠的、保序的传输:TCP
    • 多路复用、解复用
    • 拥塞控制
    • 流量控制
    • 建立连接
  • 不可靠、不保序的传输:UDP
    • 多路复用、解复用
    • 没有为尽力而为的IP服务添加更多的额外服务
  • 都不提供的服务:
    • 延时保证
    • 带宽保证

二、多路复用与解复用

2.1 多路复用

2.2 多路复用解复用工作原理

  • 解复用原理:TCP或者UDP实体采用哪些信息,将报文段的数据部分交给正确的socket,从而交给正确的进程
  • 主机收到IP数据报
    • 每个数据包有源IP地址和目标IP地址
    • 每个数据报承载一个传输层报文段
    • 每个报文段有一个源端口号和目标端口号(特定应用有著名的端口号)
  • 主机联合使用IP地址端口号将报文段发送给合适的套接字

2.3 无连接(UDP)多路解复用

  • 创建套接字:
    • 服务器端:
      • serverSocket = socket(PF_INET, SOCK_DREAM, 0);
      • bind(serverSocket, &sad, sizeof sad); // server和sad指定的端口号绑定
    • 客户端:
      • ClientSocket = socket(PF_INET, SOCK_DREAM, 0);
    • 没有Bind,ClientSocket和os为之分配的某个端口号捆绑(客户端使用什么端口号无所谓,客户端主动找服务器)
    • 接收端:
      • 在接收端,UDP套接字用二元组标识(目标IP地址、目标端口号)
      • 当主机收到UDP报文段:
        • 检查报文段的目标端口号
        • 用该端口号将报文段定位给套接字
      • 如果两个不同源IP地址/源端口号的数据报,但是有相同的目标IP地址和端口号,则被定位到相同的套接字
2.3.1 无连接多路解复用例子
  • 当主机接收到UDP段时:
    • 检查UDP段中的目标端口号
    • 将UDP段交给具备那个端口号的套接字
  • 具备相同目标IP地址和目标端口号,即使是源IP地址 或/且 源端口号不同的IP数据报,将会被传到相同的目标UDP套接字上

2.4 面向连接(TCP)的多路复用

  • TCP套接字:四元组本地标识:

    • 源IP地址
    • 源端口号
    • 目的IP地址
    • 目的端口号
  • 解复用:接收主机用这四个值来将数据报定位到合适的套接字

  • 服务器能够在一个TCP端口上同时支持多个TCP套接字:

    • 每个套接字由其四元组标识(有不同的源IP和源PORT)
  • Web服务器对每个连接客户端有不同的套接字

    • 非持久对每个请求有不同的套接字
2.4.1 面向连接的解复用:例子
  • p4, p5, p6 都运行在目标主机的80号端口
  • 主机A和C 共三个报文段全部指向相同的目标IP和目标端口80,A和C之间IP不同而加以区分,B的P2和P3因为源端口号不同加以区分
  • 在目标主机解复用传递给三个不同的应用进程
2.4.2 面向连接的多路复用:多线程Web Server

三、无连接传输:UDP

  • ""no frills" "bare bones" Internet 协议
  • "尽力而为"的服务,报文段可能丢失
    • 丢失
    • 送到应用程序的报文段乱序
  • 无连接:
    • UDP 发送端和接收端之间没有握手
    • 每个UDP报文段都被独立地处理
  • UDP 被用于:
    • 流媒体(丢失不敏感,速率敏感,应用可控制传输速率 )
    • DNS
    • SNMP
  • 在UDP上可行可靠传输
    • 在应用层增加可靠性
    • 应用特定地差错恢复

3.1 UDP:用户数据报协议

为什么要有UDP?

  • 不建立连接(会增加延时)
  • 简单:在发送端和接收端没有连接状态
  • 报文段的头部很小(开销小)
  • 无拥塞控制和流量控制:UDP可以尽可能快的发送报文段
    • 应用->传输的速率 = 主机->网络的速率

3.2 UDP校验和

**目标:**检测在被传输报文段中的差错(如比特反转)

发送方:

  • 将报文段的内容视为16比特的整数
  • 校验和:报文段的加法和(1的补运算)
  • 发送方将校验和放在UDP的校验和字段

接收方:

  • 计算接收到的报文段的校验和
  • 检查计算出的校验和与校验和字段的内容是否相等:
    • 不相等------检测到差错
    • 相等------没有检测到差错,但也许还是有差错
      • 残存错误

例子:

注意:当数字相加时,在最高位的进位要回卷,再加到结果上

例子:两个16比特的整数相加

      1 1 1 0 0 1 1 0 0 1 1 0 0 1 1 0
      1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1
      -------------------------------
回卷  1 0 1 1 1 0 1 1 1 0 1 1 1 0 1 1
      -------------------------------
  和  1 0 1 1 1 0 1 1 1 0 1 1 1 1 0 0
校验和 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 1
  • 目标端:校验范围 + 校验和 = 1111111111111111 通过校验
    • 否则没有通过校验和
  • 注:求和时,必须将进位回卷到结果上

四、可靠数据传输(rdt)的原理

  • rdt在应用层、传输层和数据链路层都很重要
  • 是网络 Top 10 问题之一

**传输层 **为上层提供的服务抽象是:数据可以通过一条可靠的信道进行传输。

  • 信道的不可靠特点决定了可靠数据传输协议( rdt )的复杂性

实现这种服务抽象是**可靠数据传输协议(reliable data transfer protocol)**的责任。然而,可靠数据传输协议的下层协议也许是不可靠的,所以十分困难。

4.1 可靠数据传输:问题描述

我们将:

  • 渐增式地开发可靠数据传输协议(rdt)地发送方和接收方
  • 只考虑单向数据传输
    • 但控制信息是双向流动
  • 双向的数据传输问题实际上是2个单向数据传输问题的综合
  • 使用有限状态机(FSM)来描述发送方和接收方

**状态:**在该状态下,下一个状态只由下一个事件唯一确定

4.1.1 Rdt1.0:在可靠信道上的可靠数据传输
  • 下层的信道完全可靠
    • 没有比特出错
    • 没有分组丢失
  • 发送方和接收方的FSM(finite state machine)
    • 发送方将数据发送到下层信道
    • 接收方从下层信道接收数据
4.1.2 Rdt2.0:具有比特差错的信道
  • 下层信道可能会出错,将分组中的比特翻转
    • 用校验和来检验比特差错
  • 问题:怎样从差错中恢复
    • **确认(ACK):**接收方显式地告诉发送方分组已被正确接收
    • **否认确认(NAK):**接收方显式地告诉发送方分组发生了差错
      • 发送方收到NAK后,发送方重传分组
  • rdt 2.0 中的新机制:采用差错控制编码进行差错检测
    • 发送方差错控制编码、缓存
    • 接收方使用编码检错
    • 接收方的反馈:控制报文(ACK,NAK):接收方 -> 发送方
    • 发送方收到反馈相应的动作

FSM描述

4.1.3 Rdt2.1

Rdt2.0 的致命缺陷

  • 如果ACK/NAK出错?
    • 发送方不知道接收方发生了什么事情!
    • 发送方如何做?
      • 重传?可能重复
      • 不重传?可能死锁(或出错)
    • 需要引入新机制
      • 序号
  • 处理重复
    • 发送方在每个分组中加入序号
      • 我们仅需0、1即可进行区分
    • 如果ACK/NAK出错,发送方重传当前分组
    • 接收方丢弃(不发给上层)重复分组

停等协议

++发送方发送一个分组,然后等待接收方的应答。++

发送方处理出错的ACK/NAK

接收方处理出错的ACK/NAK

发送方:

  • 在分组中加入序列号
  • 两个序列号(0,1)就足够了
    • 一次只发送一个未经确认的分组
  • 必须检测ACK/NAK是否出错(需要EDC)
  • 状态数变成了两倍
    • 必须记住当前分组的序列号为0还是1

接收方:

  • 必须检测接收到的分组是否是重复的
    • 状态会指示希望接收到的分组的序号为0还是1
  • 注意:接收方并不知道发送方是否正确收到了其ACK/NAK
    • 没有安排确认的确认

接收方不知道它最后发送的**ACK **/ NAK是否被正确地收到

  • 发送方不对收到的ACK/NAK给确认,没有所谓的确认的确认
  • 接收方发送ACK,如果后面接收方收到的是:
    • 老分组P0?则ACK错误
    • 下一个分组?P1,ACK正确
4.1.4 Rdt2.2:无NAK的协议
  • 功能同Rdt2.1,但只使用ACK(ack 需要编号)
  • 接收方对最后 正确接收的分组发ACK,以替代NAK
    • 接收方必须显式地包含被正确接收的分组的序号
  • 当收到重复的ACK(如:再次收到ACK0)时,发送方与收到NAK采取相同的动作:重传当前分组
    • 通过发送重复的ACK来替代NAK的发送
  • 为后面的一次发送多个数据单位做一个准备
    • 一次能够发送多个
    • 每一个的应答都有:ACK,NACK:麻烦
    • 使用对前一个数据单位的ACK,代替本数据单位的NAK
    • 确认信息减少一半,协议处理简单

FSM

逻辑还是很简单的

4.1.5 Rdt3.0:具有比特差错和分组丢失的信道

**新的假设:**下层信道可能会丢失分组(数据或ACK)

  • 会死锁
  • Rdt2.2的机制还不够处理这种状况:
    • 校验和
    • 序列号
    • ACK
    • 重传

方法:发送方等待ACK一段合理的时间

  • 发送端超时重传:如果到时没有收到ACK->重传
  • 问题:如果分组(或ACK)只是被延迟了
    • 重传将会导致数据重复,但利用序列号已经可以处理这个问题
    • 接收方必须指明被正确接收的序列号
  • 需要一个倒计数定时器

发送方的FSM

Rdt3.0 运行

  • 如果超时定时器设置的不合理,导致过早地超时重传,那么会使得多次重发packet,但是不会出错。但是效率比较低,一半的分组和确认时重复的
  • 设置一个合理的超时时间也非常重要

Rdt3.0 的性能

  • Rdt3.0 可以工作,但链路容量比较大的情况下,性能很差
    • 链路容量很大,一次发一个PDU 的不能够充分利用链路的传输能力
  • 例:1 Gbps 的链路,15ms端-端传播延时,分组大小为1KB:
  • U s e n d e r = 利用率 − 忙于发送的时间比例 U_{sender} = 利用率 - 忙于发送的时间比例 Usender=利用率−忙于发送的时间比例
  • 每30ms发送1KB的分组->270Kbps = 33.75kB/s 的吞吐量(在1Gbps链路上)
  • 瓶颈在于: 网络协议限制了物理资源的利用!
  • 协议本身只允许一次发一个,导致利用率太低了!
  • 如何解决?------流水线协议
4.1.6 流水线:提高链路利用率

增加每次发送分组的数目,极大地提高了链路利用率

随着n的增大,瓶颈将会转移到链路带宽上

流水线:允许发送方在未得到对方确认 的情况下一次发送多个分组

  • 必须增加序号的范围:用多个bit表示分组的序号
  • 在发送方/接收方要有缓冲区
    • 发送方缓冲:未得到确认,可能需要重传
    • 接收方缓冲:上层用户取用数据的速率 ≠ 接收到的数据速率;接收到的数据可能乱序,排序交付(可靠)

两种通用的流水线协议:回退N步(GBN)选择重传(SR)

4.2 通用:滑动窗口(slide window)协议

  • 发送缓冲区
    • 形式:内存中的一个区域,落入缓冲区的分组可以发送
    • 功能:用于存放已发送,但是没有得到确认的分组
    • 必要性:需要重发时可用
  • 发送缓冲区的大小:一次最多可以发送多少个未经确认的分组
    • 停止等待协议=1
    • 流水线协议>1,合理的值,不能很大,链路利用率不能够超100%
  • 发送缓冲区中的分组
    • 未发送的:落入发送缓冲区的分组,可以连续发送出去;
    • 已经发送出去的、等待对方确认的分组:发送缓冲区的分组只有得到确认才能删除
4.2.1 发送窗口滑动过程------相对表示法
  • 采用相对移动方式表示,分组不动
  • 可缓冲范围移动,代表一段可以发送的权力
4.2.2 滑动窗口(slide window)协议
  • 发送窗口:发送缓冲区内容的一个范围
    • 那些已发送 但是未经确认分组的序号构成的空间
  • 发送窗口的最大值 <= 发送缓冲区的值
  • 一开始:没有发送任何一个分组
    • 后沿 = 前沿
    • 之间为发送窗口的尺寸=0
  • 每发送一个分组,前沿前移一个单位

发送窗口的移动->前沿移动

  • 发送窗口前沿移动的极限:不能够超过发送缓冲区

发送窗口的移动->后沿移动

  • 条件:收到老分组的确认
  • 结果:发送缓冲区罩住新的分组,来了分组可以发送
  • 移动的极限:不能够超过前沿
4.2.2.1 发送窗口(sending window)
4.2.2.2 接收窗口(receving window)

接收窗口(receiving window)= 接收缓冲区

  • 接收窗口用于控制哪些分组可以接收

    • 只有收到分组序号落入接收窗口内才允许接收
    • 若序号在接收窗口之外,则丢弃
  • 接收窗口尺寸Wr = 1,则只能顺序接收

  • 接收窗口尺寸Wr > 1,则可以乱序接收

    • 但是提交给上层的分组,要按序
  • 例子:Wr = 1,在0的位置:只有0号分组可以接收

    向前滑动1个,罩在1的位置,如果来了第2号分组,则丢弃,因为第2号分组不在窗口内

  • 接收窗口的滑动和发送确认
    • 滑动:
      • 低序号的分组到来,接收窗口移动
      • 高序号分组乱序到来,缓存但不交付(因为要实现rdt,不允许失序),不滑动
    • 发送确认:
      • 接收窗口尺寸=1:发送连续收到的最大分组确认(GBN协议,累计确认,即发送一个确认,代表前面的分组都已确认)
      • 接收窗口尺寸>1:收到分组,发送那个分组的确认(SR协议,非累计确认)
4.2.3 正常情况下两个窗口间的互动
  • 发送窗口
    • 有新的分组落入发送缓冲区范围,发送->前沿滑动
    • 来了老的低序号分组的确认->后沿向前滑动->新的分组可以落入发送给缓冲区的范围
  • 接收窗口
    • 收到分组,落入到接收窗口范围内,接收
    • 是低序号,发送确认给对方
  • 发送端上面来了分组->发送窗口滑动->接收窗口滑动->发确认
4.2.4 异常情况下GBN的2窗口互动
  • 发送窗口
    • 新分组落入发送缓冲区范围,发送->前沿滑动
    • 超时重发机制让发送端将发送窗口中的所有分组发送出去
    • 来了老分组的重复确认->后沿不向前滑动->新的分组无法落入发送缓冲区的范围(此时如果发送缓冲区有新的分组可以发送)
  • 接收窗口
    • 收到乱序分组,没有落入到接收窗口的范围内,抛弃
    • (重复)发送老分组的确认,累计确认
4.2.5 异常情况下SR的2窗口互动
  • 发送窗口
    • 新分组落入发送缓冲区范围,发送->前沿滑动
    • 超时重发机制让发送端将超时的分组重新发送出
    • 来了乱序分组的确认->后沿不向前滑动->新的分组无法落入发送缓冲区的范围(此时如果发送缓冲区有新的分组可以发送)
  • 接收窗口
    • 收到乱序分组,落入到接收窗口的范围内,接收
    • 发送该分组的确认,单独确认
4.2.6 GBN协议和SR协议的异同
  • 相同之处
    • 发送窗口>1
    • 一次能够可发送多个未经确认的分组
  • 不同之处
    • GBN(Go Back N) :接收窗口尺寸=1
      • 接收端:只能顺序接收
      • 发送端:从表现来看,一旦一个分组没有发成功,如:0,1,2,3,4;假如1未成功,234都发出去了,要返回1再发送:GB1(Go Back to 1)
    • SR(Selective repeat) :接收窗口尺寸>1
      • 接收端:可以乱序接收
      • 发送端:发送0,1,2,3,4,一旦1未成功,2,3,4 已发送,无需重发,选择性发送1(Selective repeat 1)
4.2.7 流水线协议:总结

Go-back-N:

  • 发送端最多在流水线中有N个未确认的分组
  • 接收端只是发送累计型确认cumulative ack
    • 接收端如果发现gap,不确认新到来的分组
  • 发送端拥有对最老的未确认分组的定时器
    • 只需设置一个定时器
    • 当定时器到时时,重传所有未确认分组

Selective Repeat

  • 发送端最多在流水线中有N个未确认的分组
  • 接收方对每个到来的分组单独确认individual ack(非累计确认)
  • 发送方为每个未确认的分组保持一个定时器
    • 当超时定时器到时时,只是重发到时的未确认分组

GBN:发送方扩展的FSM

GBN:接收方扩展的FSM

选择重传SR

  • 接收方对每个正确接收的分组,分别发送 ACKn (非累计确认)
    • 接收窗口 > 1
      • 可以缓存乱序的分组
    • 最终将分组按顺序交付给上层
  • 发送方只对那些没有收到ACK的分组进行重发------选择性重发
    • 发送方为每个未确认的分组设定一个定时器
  • 发送窗口的最大值(发送缓冲区)限制发送未确认分组的个数

选择重传

选择重传SR的运行

对比GBN和SR

  • 适用范围
    • 出错率低:比较适合GBN,出错非常罕见,没有必要用复杂的SR,为罕见的事件做日常的准备和复杂处理
    • 链路容量大(延迟大、带宽大):比较适合SR而不是GBN,一点出错代价太大
4.2.8 思考题:窗口的最大尺寸

序号大小与窗口大小之间的关系?

假如用 n bit 来代表分组序号,那么 GBN 发送窗口最大尺寸为:2^n - 1SR 发送窗口最大尺寸为:2^(n - 1)

原因:

窗口协议中,序号是循环使用的(序号 mod 2^n 循环使用),当发送窗口过大,会导致序号回绕时,接收方无法确认该分组是旧的分组还是新的分组。

对于GBN:如果我们大于 2^n - 1,比如 2^n,那么我们发送了 2^n 的分组后,发送方会再次从0开始发送,这个时候,接收方就分不清到底是旧分组的重发还是新的分组了。比如 你后沿把0扔出去,前沿 0又进来了,发送0,接收方看来,这可能是旧0的重发,也可能是新0.

对于SR:2^{n - 1} 的大小 保证了 [0, 2^{n - 1} - 1] 和 [2^{n - 1}, 2^n - 1] 在两个窗口内,当序号回绕时,新窗口的分组序号和上一个窗口的分组序号不同,接收方可以判断是新窗口的分组还是旧窗口的分组重传

五、面向连接的传输:TCP

5.1 概述

  • 点对点

    • TCP连接是点对点的,一个发送方,一个接收方
  • 可靠的、按顺序的字节流:

    • 没有报文边界
  • 管道化(流水线)

    • TCP拥塞控制和流量控制设置窗口大小
  • 发送和接收缓存

    • 发送方发送的数据由TCP引导到发送缓存,适时发送,相对应的,会存在一个接收缓存
  • 全双工数据:

    • 在同一连接中数据流双向流动
      • MSS(max segment size) :报文段里应用层数据的最大长度,而不是指包括首部的TCP报文段的最大长度
  • 面向连接:

    • 在数据交换之前,通过握手(交换控制报文)初始化发送方、接收方的状态变量
  • 有流量控制:

    • 发送方不会淹没接收方

5.2 TCP 报文段结构

字节流会被划分为一个个的MSS,TCP为每块客户数据配上一个TCP首部,从而形成多个TCP报文段(TCP segment)

TCP报文段的结构如下:

  • 源端口号、目标端口号
  • 序号和确认号用于实现rdt
  • 首部长度
  • 6个标志字段:
    • U:紧急数据
    • A:ACK,用于指示字段中的值是有效的
    • P:PSH:马上推出数据,即置1时,接收方应立即将数据交给上层
    • RST,SYN,FIN 的组合用于连接的建立和拆除

TCP 序号、确认号

序号:

  • 报文段首字节在字节流的编号

确认号

  • 期望从另一方收到的下一个字节的序号
  • 累积确认
  • 确认号有没有用:看 ACK标志位

Q:接收方如何处理乱序的报文段?

A:没有规定,取决于实现者自己

  • A 发送第42字节,期望B从79开始传
  • B 发送第79个字节,期望A从43开始传
  • ......

TCP往返延时(RTT)和超时

**Q:**怎样设置TCP超时?

  • 比 RTT 要长
    • 但 RTT 是变化的
  • 太短:太早超时
    • 不必要的重传
  • 太长:对报文段丢失反应太慢,消极

Q:怎样估计RTT?

  • SampleRTT :测量从报文段发出到收到确认的时间
    • 如果有重传,忽略此次测量
  • SampleRTT 会变化,因此估计的RTT 应该比较平滑
    • 对几个最近的测量值求平均 ,而不是仅用当前的SampleRTT

如何求平均?------指数加权

EstimatedRTT = (1 - α) * EstimatedRTT + α * SampleRTT

  • 指数加权移动平均
  • 过去样本的影响呈指数衰减
  • α 推荐值: = 0.125 R

设置超时

  • EstimatedRTT + 安全边界时间

    • EstimatedRTT 变化大(方差大)->较大的安全边界时间
  • SampleRTT 会偏离 EstimatedRTT多远(也是用指数加权平均来计算):

    **DevRTT = (1 - β) * DevRTT + β * |SampleRTT - EstimatedRTT| **

    (推荐值:β = 0.25)

超时时间间隔设置为:

TimeoutInterval = EstimatedRTT + 4 * DevRTT

5.3 可靠数据传输

  • TCPIP 不可靠服务的基础上建立了rdt
    • 管道化的报文段
      • GBN or SR
    • 累计确认(像GBN)
    • 单个重传定时器(像GBN)
    • 是否可以接受乱序的,没有规范
  • 通过以下事件触发重传
    • 超时(只重发那个最早的未确认段:SR)
    • 重复的确认
      • 例子:收到了 ACK50,之后又收到了3个ACK50
  • 首先考虑简化的TCP发送方:
    • 忽略重复的确认
    • 忽略流量
5.3.1 TCP发送方(简化版)
5.3.2 TCP 发送方事件:

从应用层接收数据:

  • 从 nextseq 创建报文段

  • 序号 nextseq 为报文段首字节的字节流编号

  • 如果还没有运行,启动定时器

    • 定时器与最早未确认的报文段关联

    • 过期间隔

      TimeOutInterval

超时:

  • 重传后沿最老的报文段
  • 重新启动定时器

收到确认:

  • 如果是对尚未确认的报文段确认
    • 更新已被确认的报文序号
    • 如果当前还有未被确认的 报文段,重新启动定时器
  • 注释:
    • SendBase - 1:最后一个累积确认的字节
5.3.3 TCP:重传
5.3.4 产生TCP-ACK的建议
  • case1:不立即发ACK,在超时时间内等待别的报文段,如果实在没有的话,则发送一个ACK
  • case2:当前已经攒了一个ACK,然后又到了一个按序报文段,赶紧把手里这个发出去
  • case3:乱序到达一个报文段,那么就发送重复ACK
  • case4:乱序到了一个报文段产生了一个gap:
    • 如果来了个完全补齐gap的报文段,那么赶紧发送乱序报文段的期待

    • 如果是部分补齐gap,假如填充到y1,那么发送起始字节为y1的期待

5.3.5 快速重传
  • 超时周期往往太长:

    • 在重传丢失报文段之前的延时太长
  • 通过重复的ACK来检测报文段丢失

    • 发送方通常连续发送大量报文段
    • 如果报文段丢失,通常会引起多个ACK重复
  • 如果发送方收到同一数据 的3个冗余ACK,重传最小序号的段:

    • 快速重传:在定时器过时之前重发报文段

    • 它假设跟在被确认的数据后面的数据丢失了

      • 第一个ACK是正常的

      • 收到第二个该段的ACK,表示接收方收到一个该段后的乱序段

      • 收到第3、4个该段的ACK,表示接收方收到该段后的2、3个乱序段

        说明:该段很可能丢失了!!!直接在超时之前重发

下面是 富哥速速v我50的例子(

快速重传算法

else 逻辑隐含的是:y = base,因为base前面的都已经确认所以不可能存在 y < base

5.4 流量控制

流量控制:接收方控制发送方,不让发送方发送的太多、太快以至于让接收方的缓冲区溢出

  • 接收方在其向发送方的TCP 段头部的rwnd 字段"通告"其空闲buffer 大小
    • RcvBuffer 大小通过 socket 选项设置(典型默认大小为4096字节)
    • 很多操作系统自动调整RcvBuffer
  • 发送方限制未确认("in-flight")字节的个数 ≤ 接收 方发送过来的 rwnd 值
  • 保证接收方不会被淹没(不会缓冲区溢出)

5.5 连接管理

  • 在正式交换数据之前,发送方和接收方握手建立通信关系:
    • 同意建立连接(每一方都知道对方愿意建立连接)
    • 同意连接参数
5.5.1 同意建立连接

在网络中,2次握手建立连接可行吗?

  • 变化的延迟(连接请求的段没有丢,但可能超时)
  • 由于丢失造成的重传 (e.g. req_conn(x))
  • 报文乱序
  • 相互看不到对方

2次握手的失败场景:

  • 发了两个连接请求
  • 建立连接后,发送两次数据
  • 结束后,老请求终于到达了服务器,又建立了连接
  • 老数据也终于到达了服务器,被接受
  • 啊?
5.5.2 TCP 3次握手

解决方案:变化的初始序号+双方确认对方的序号(3次握手)

3次握手解决:半连接和接收老数据问题

对于半连接:老 req 的 acc 会被拒绝掉

对于接收老数据:

  1. 情况1:由于连接不存在,数据会被扔掉
  2. 情况2:由于序号不在当前序号范围内,所以被扔掉
  3. 我们不得不承认,序号回滚回来会有旧数据的序号在当前范围内的可能,但是概率很低。网络无法解决所有问题

3次握手的有限状态机:

5.5.3 关闭连接
  • 客户端、服务器分别关闭他自己这一侧的连接
    • 发送 FIN bit = 1 的 TCP 段
  • 一旦接收到FIN,用ACK回应
    • 接到FIN段,ACK可以和它自己发出的FIN段一起发送
  • 可以处理同时的FIN交换
  • 客户端发送FIN = 1,进入FIN-WAIT1状态
  • 接收到 服务器的ACK,进入 FIN-WAIT2状态
  • 收到服务器的FIN = 1 或者 超时,关闭连接

前面也说了网络无法解决所有的问题,TCP 的3次握手为 SYN 洪泛攻击提供了环境。

在三次握手下,服务器得到一个 SYN 会建立半连接并分配资源,当超时后才会断开并回收。

攻击者发送大量的TCP SYN 报文段,导致服务器不断建立半连接,使得服务器资源消耗殆尽。

现在大多数主流操作系统都部署了SYN cookie来防御这类攻击。

六、拥塞控制原理

拥塞:

  • 非正式的定义:"太多的数据需要网络传输,超过了网络的处理能力"
  • 与流量控制不同
  • 拥塞的表现:
    • 分组丢失(路由器缓冲区溢出)
    • 分组经历比较长的延迟(在路由器的队列中排队)
  • 网络中前10位的问题

6.1 拥塞的原因/代价:场景1

  • 2个发送端,2个接收端
  • 一个路由器,具备无限大的缓冲
  • 输出链路带宽:R
  • 没有重传

缓冲无限大的情况下,分组不会丢,但是会让延迟大的难以接受。

6.2 拥塞的原因/代价:场景2

  • 一个路由器,有限的缓冲
  • 分组丢失时,发送端重传
    • 应用层的输入 = 应用层的输出: λ i n = λ o u t \lambda_{in} = \lambda_{out} λin=λout
    • 传输层的输入包括重传: λ i n ′ ≥ λ i n \lambda'{in} \ge \lambda{in} λin′≥λin

理想化:发送端有完美的信息

发送端知道什么时候路由器的缓冲是可用的

  • 在缓冲可用时发送
  • 不会丢失: λ i n ′ = λ i n \lambda'{in} = \lambda{in} λin′=λin

理想化: 掌握丢失信息

  • 分组可以丢失,在路由器由于缓冲器满而被丢弃
  • 如果知道分组丢失了,发送方重传分组

现实情况:重复

  • 分组可能丢失,由于缓冲器满而被丢弃
  • 发送端最终超时,发送第2个拷贝,2个分组都被传出

输出比输入少原因:

  1. 重传的丢失分组
  2. 没有必要重传的重复分组

拥塞的"代价":

  • 为了达到一个有效输出,网络需要做更多的工作(重传)
  • 没有必要的重传,链路中包括了多个分组的拷贝
    • 是那些没有丢失,经历的时间比较长(拥塞状态)但是超时的分组
    • 降低了的"goodput"

6.3 拥塞的原因/代价:场景3

  • 4个发送端
  • 多重路径
  • 超时 / 重传

**Q:**当 λ i n λ i n ′ 增加时,会发生什么? \lambda_{in} \lambda'_{in} 增加时,会发生什么? λinλin′增加时,会发生什么?

**A:**当红色的 λ i n ′ \lambda'_{in} λin′ 增加时,所有到来的蓝色分组都在最上方的队列中丢弃了,蓝色吞吐->0

又一个拥塞的代价:

  • 下游路由器的分组丢失时,相当于上游白传输了,造成了上游传输能力的浪费

6.4 拥塞控制方法

2种常用的拥塞控制方法:

端到端拥塞控制:

  • 没有来自网络的显示反馈
  • 端系统根据延迟和丢失事件推断是否有拥塞
  • TCP采用的方法

网络辅助的拥塞控制:

  • 路由器提供给端系统以反馈信息
    • 单个 bit 置位,显示有拥塞 (SNA,DECbit,TCP/IP ECN,ATM)
    • 显式提供发送端可以 采用的速率
6.4.1 案例学习: ATM ABR 拥塞控制

ABR:available bit rate:

  • "弹性服务"
  • 如果发送端的路径"轻载"
    • 发送方使用可用带宽
  • 如果发送方的路径拥塞了
    • 发送方限制其发送的 速度到一个最小保障 速率上

RM (资源管理) 信元:

信元可以看作一个分组:53字节,其中5个字节为头部

  • 向发送端发送,在数据信元中间隔插入
  • RM信元中的比特被交换机设置("网络辅助")
    • NI bit:no increase in rate(轻微拥塞)速率不要增加了
    • CI bit:congestion indication 拥塞指示
  • 发送端发送的RM信元被接收端返回,接收端不做任何改变
  • RM 信元中的2 个字节 **ER (explicit rate)**字段
    • 拥塞的交换机可能会降低信元中ER的值
    • 发送端发送速度因此是最低的可支持速率
  • 数据信元中的EFCI bit : 被拥塞的交换机设置成1
    • 如果在管理信元RM前面的数据信元EFCI被设置成了1, 接收端在 返回的RM信元中设置CI bit

七、TCP 拥塞控制

7.1 机制

  • 端到端的拥塞控制机制
    • 路由器不向主机有关拥塞的反馈信息
      • 路由器的负担较轻
      • 符合网络核心简单的 TCP/IP 架构原则
    • 端系统根据自身得到的信息,判断是否发生拥塞,从而采取动作

拥塞控制的几个问题

  • 如何检测拥塞
    • 轻微拥塞
    • 拥塞
  • 控制策略
    • 在拥塞发送时如何动作,降低速率
      • 轻微拥塞,如何降低
      • 拥塞时,如何降低
    • 在拥塞缓解时如何动作,增加速率

7.2 拥塞感知

发送端如何探测到拥塞?

  • 某个段超时了(丢失事件):拥塞
    • 超时时间到:某个段的确认没有到来
    • 原因1:网络拥塞 (某个路由器缓冲区没空间了,被丢弃)概率大
    • 原因2:出错被丢弃了 (各级错误,没有通过校验,被丢弃)概率小
    • 一旦超时,就认为拥塞了,有一定误判,但是总体控制方向是对的
  • 有关某个段的3次重复ACK:轻微拥塞
    • 段的第1个ack,正常,确认绿段,期待红段
    • 段的第2个重复ack,意味着红段的后一段收到了,蓝段乱序到达
    • 段的第2、3、4个ack重复,意味着红段的后第2、3、4个段收到了 ,橙段乱序到达,同时红段丢失的可能性很大(后面3个段都到了, 红段都没到)
    • 网络这时还能够进行一定程度的传输,拥塞但情况要比第一种好

7.3 速率控制方法

如何控制发送端发送的速率

  • 维持一个拥塞窗口的值:CongWin(Congestion Window)
  • 发送端限制已发送但是未确认 的数据量(的上限):
    • LastByteSent-LastByteAcked <= CongWin
  • 从而粗略地控制发送方的往网络中注入的速率
  • CongWin是动态的,是感知到的网络拥塞程度的函数
    • 超时或者3个重复ack,CongWin降低
      • 超时时:CongWin 降为1MSS,进入**SS(slow start)**阶段然后再倍增到CongWin / 2(每个RTT),从而进入CA阶段
      • 3个重复ack :CongWin降为CongWin / 2,CA阶段
    • 否则(正常收到Ack,没有发送以上情况):CongWin跃跃欲试
      • SS阶段:加倍增加(每个RTT)
      • CA阶段:线性增加(每个RTT)

7.4 TCP拥塞控制和流量控制的联合动作

联合控制的方法:

  • 发送端控制 发送但是未确认的量 同时也不能够超过接收窗口,满足流量控制要求
    • SendWin = min(CongWin, RecvWin)
    • 同时满足拥塞控制和流量控制要求
7.4.1 策略概述

拥塞控制策略:

  • 慢启动
  • AIMD:线性增、乘性减少
  • 超时事件后的保守策略
7.4.2 TCP慢启动
  • 连接刚建立,CongWin = 1MSS

    • 如:MSS=1460bytes & RTT = 200 ms
    • 初始速率 = 58.4kbps
  • 可用带宽可能 >> MSS / RTT

    • 应该尽快加速,到达希望的速率
  • 当连接开始时,指数性增加发送速率,知道发生丢失的事件

    • 启动初值很低
    • 但是速度很快
  • 当连接开始时,指数性增加(每个RTT)发送速率直到发生丢失事件

    • 每一个RTT,CongWin加倍
    • 每收到一个ACK时,CongWin加1
    • 慢启动阶段:只要不超时或3个重复ACK,一个RTT,CongWin加倍
  • **总结:**初始速率很慢,但是加速却是指数性的

    • 指数增加,SS时间很短,长期来看可以忽略
7.4.3 AIMD(Additive- Increase, Multiplicative- Decrease)

乘性减:

  • 丢失事件后将CongWin降为1,将CongWin / 2作为阈值,进入慢启动阶段(倍增直到CongWin / 2)

加性增:

  • 当CongWin > 阈值时,一个RTT如果没有发生丢失事件,将CongWin 加 1MSS:探测
  • 当收到3个重复的ACKs:
    • CongWIn 减半
    • 窗口(缓冲区大小)之后线性增长
  • 超时 事件发生时:
    • CongWin被设置为1MSS ,进入SS阶段
    • 之后窗口指数增长
    • 增长到一个阈值(上次发生拥塞的窗口的一半)时,再线性增加

思路

  • 3 个重复的ACK表示网络还有一定的段传输能力
  • 超时之前的3个重复的ACK表示"警报"
7.4.4 改进

什么时候应该将 指数性增长变成 线性?

在超时之前,当CongWin变成上次发生超时的窗口的一半

实现:

  • 变量:Threshold
  • 出现丢失,Threshold设置成CongWin的1/2

7.5 总结

  • 当 CongWin < Threshold,发送端处于慢启动阶段(slow-start),窗口指数性增长
  • 当 CongWin > Threshold,发送端处于拥塞避免阶段(congestion-avoidance),窗口线性增长
  • 当 收到三个重复的ACKs(triple,duplicate ACK ),Threshold设置成CongWin/2,CongWin=Threshold+3
  • 当 超时事件发生时timeout,Threshold=CongWin/2,CongWin = 1MSS,进入SS阶段

TCP发送端拥塞控制

7.6 TCP吞吐量

  • TCP 平均吞吐量是多少,使用窗口window 尺寸WRTT 来描述?
    • 忽略慢启动阶段,假设发送端总有数据传输
  • W :发生丢失事件时的窗口尺寸(单位:字节)
    • 平均窗口尺寸(#in-flight字节):3/4W(因为W的变化范围是W/2和W,取均值就是3/4)
    • 平均吞吐量:RTT时间吞吐3/4W

7.7 TCP公平性

**公平性目标:**如果K个TCP会话分享一个链路带宽为R的瓶颈,每一个会话的有效带宽为R / K

为什么TCP是公平的?

2个竞争的TCP会话:

  • 加性增加,斜率为1,吞吐量增加
  • 乘性减,吞吐量比例减少

上图含义:

  • 假如我们有两个会话A,B之间竞争带宽,一开始A带宽远大于B
  • 我们忽略慢启动阶段,因为增长的太快了
  • 那么在加性加阶段,二者每个RTT增加1,也就是斜率为1增长(图中红线)
  • 当超过threshold后,各自会被调整到原来的一半,然后再次以斜率为1增长
  • ......
  • 我们发现每调整一次,二者的差距都会缩小,越来越逼近公平的状态
  • 所以,TCP是公平的

公平性和UDP

  • 多媒体应用通常不是TCP
    • 因为应用发送的数据速率希望不受拥塞控制的影响
  • 使用UDP
    • 音视频应用泵出数据的速率是恒定的,忽略数据的丢失
  • 研究领域:TCP友好性

公平性和并行TCP连接

  • 2个主机间可以打开多个并行的TCP连接
  • Web浏览器
  • 例如:带宽为R 的链路支持了9个连接
    • 如果新的应用要求建1个TCP连接,获得带宽R/10
    • 如果新的应用要求建立11个连接,那么获得带宽R/2

八、总结

  • 传输层提供的服务
    • 应用进程间的逻辑通信
      • vs 网络层提供的主机到主机的通信服务
    • 互联网上传输层协议:UDP、TCP
      • 特性
  • 多路复用和解复用
    • 端口:传输层的SAP
    • 无连接的多路复用和解复用
    • 面向连接的多路复用和解复用
  • 实例1:无连接传输层协议UDP
    • 多路复用解复用
    • UDP报文格式
    • 检错机制:校验和
  • 可靠数据传输原理
    • 问题描述
    • 停止等待协议
      • rdt 1.0,2.0,2.1,2.2,3.0
    • 流水线协议
      • GBN
      • SR
  • 实例2:面向连接的传输层协议TCP
    • 概述:TCP特性
    • 报文段格式
      • 序号,超时机制及时间
    • TCP可靠传输机制
    • 重传,快速重传
    • 流量控制
    • 连接管理
      • 三次握手
      • 对称连接释放
  • 拥塞控制原理
    • 网络辅助的拥塞控制(例:ATM)
    • 端到端的拥塞控制(例:TCP)
  • TCP的拥塞控制
    • AIMD
    • 慢启动
    • 超时之后的保守策略
相关推荐
记得多喝水o10 分钟前
docker环境部署zabbix
运维·网络·网络协议·tcp/ip·信息与通信
小翼不想投降1 小时前
安全见闻全解析
网络·安全·web安全
Yan-英杰2 小时前
利用代理IP爬取Zillow房产数据用于数据分析
网络·python·网络协议·tcp/ip·数据分析
期待未来的男孩2 小时前
SEC_ASA 第二天作业
网络·windows·智能路由器
drebander4 小时前
手撕 HttpClient:自己实现简单的 HTTP 请求工具
java·网络
冰红茶兑滴水4 小时前
HTTP 协议
linux·网络·c++·网络协议·http
安迪范德4 小时前
netty 实现http
网络·网络协议·http
nongcunqq4 小时前
不能通过 ip 直接访问 共享盘 解决方法
网络·网络协议·tcp/ip
qq_459238494 小时前
Linux之网络配置
linux·网络