• 计算机网络第三章知识点回顾(自顶向下)


    系列文章戳这里👇

    1. 计算机网络第一章知识点总结
    2. 计算机网络第二章知识点总结
    3. 计算机网络第三章知识点总结
    4. 计算机网络第四章知识点总结
    5. 计算机网络第五章知识点总结
    6. 计算机网络第六章知识点总结
    7. 计算机网络第七章知识点总结
    8. 计算机网络第八章知识点总结

    1.传输层概述

    1. Our goals:
      • 理解传输层服务原理:
        • 多路复用与多路分解
        • 可靠数据传输
        • 流量控制
        • 拥塞控制
    2. 学习因特网的传输层协议:
      • UDP: 无连接传输
      • TCP: 面向连接的传输
      • TCP拥塞控制
    3. 传输层把 应用层报文 (message) 转换成传输层分组, 即报文段(segment) .
      • 主要协议有 UDP 和 TCP 协议.
    4. 网络层提供主机之间的逻辑通信;
      • 传输层提供进程之间的逻辑通信 .
      • 传输层依赖并增强网络层的服务 .

    1.1传输服务

    1. 在应用程序看来:
      • 源进程向本地套接字写入报文或数据,目的进程在本地套接字即可收到报文或数据
      • 源进程和目的进程仿佛直接连接在一起
      • 传输层提供了进程间的逻辑通信
    2. 在传输层看来:
      • 发送方传输层将报文交给本地网络层接口,接收方传输层从本地网络层接口即可收到报文
      • 网络层提供了终端间的逻辑通信

    1.2传输层与网络层的关系

    1. 网络层:提供主机之间的逻辑通信
    2. 传输层:提供进程之间的逻辑通信
    3. 传输层依赖并增强网络层服务
    4. 网络层提供尽力而为的服务:
      • 网络层尽最大努力在主机间交付分组,但不提供任何承诺
      • 具体来说,不保证交付,不保证按序交付,不保证数据完整,不保证延迟,不保证带宽,……
    5. 传输层不能提供的服务:
      • 延迟保证
      • 带宽保证
    6. 传输层可以提供的服务:
      • 保证可靠、按序的交付:TCP
      • 不保证可靠、按序的交付:UDP

    2.多路复用与解复用

    1. 传输层基本服务
      • 将主机间交付扩展到进程间交付
    2. (发送端)多路复用:
      • 传输层从多个套接字收集数据,交给网络层发送
    3. (接收端)解复用:
      • 传输层将收到的数据交付到正确的套接字 How?—(通过 套接字 标识)

    2.1如何进行多路复用和解复用

    1. 为将邮件交付给收信人
      • 每个收信人应有一个信箱,写有收信人地址和姓名(唯一标识)
      • 信封上有收信人地址和名字
    2. 为将报文段交付给套接字
      • 主机中每个套接字应分配一个唯一的标识
      • 报文段中包含接收套接字的标识
    3. 多路复用
      • 发送方传输层将源/目的套接字标识置于报文段中,交给网络层
    4. 解复用
      • 接收方传输层根据报文段中的目的套接字标识,将报文段交付到正确的套接字

    2.2套接字与端口号

    1. 端口号是套接字标识的一部分
      • 每个套接字在本地关联一个端口号
    2. 端口号:
      • 一个16比特的数
      • 0~1023由公共域协议使用,称众所周知的端口号
    3. 报文段中有两个字段携带端口号
      • 源端口号:与发送进程关联的本地端口号
      • 目的端口号:与接收进程关联的本地端口号

    2.2.1如何分配UDP套接字的端口号

    1. 自动分配:

      • 例如,new Datagramsocket(),不指定端口号
      • 通常由操作系统从1024~65535中分配
      • 客户端通常使用这种方法
    2. 使用指定端口号创建套接字:

      • 例如,new Datagramsocket(53)
      • 实现公共域协议的服务器应分配众所周知的端口号
      • 服务器通常采用这种方法
    3. UDP套接字标识为二元组

    2.2.2UDP解复用

    1. 接收方传输层收到一个UDP报文后:
      • 检查报文中的目的端口号,将UDP报文交付到具有该端口号的套接字
      • <目的IP地址,目的端口号> 相同的UDP报文被交付给同一个套接字,与 <源IP地址,源端口号> 无关
      • 报文中的 <源IP地址,源端口号> 被接收进程用来发送响应报文

    2.2.3创建TCP套接字

    1. 服务器在port=x创建一个欢迎套接字:
      • welcomeSocket = new ServerSocket(x)
    2. 客户A创建一个与欢迎套接字通信的客户套接字(假设自动分配端口号y):
      • clientSocket = new Socket(“hostname”, x)
    3. 服务器在收到客户A的连接请求后创建一个连接套接字:
      • connectionSocket = welcomeSocket.accept()
      • 该连接套接字只与客户A的套接字通信,即只接收具有以下四元组的报文段:
        • 源IP地址 = 客户A的IP地址
        • 源端口号 = y
        • 目的IP地址 = 服务器的IP地址
        • 目的端口号= x
    4. 不同的客户进程与服务器上不同的连接套接字对应

    2.2.4TCP解复用

    1. 服务器主机可能有多个连接套接字
    2. 每个连接套接字与一个进程相联系,并由 <源IP地址,目的IP地址,源端口号,目的端口号> 四元组进行标识
    3. 服务器使用该四元组将报文段交付到正确的连接套接字

    小结

    1. UDP套接字

      • 使用二元组标识套接字
      • 服务器使用一个套接字服务所有客户
    2. TCP套接字

      • 使用<源IP地址,目的IP地址,源端口号,目的端口号> 四元组标识连接套接字
      • 服务器使用多个连接套接字,每个连接套接字服务一个客户
    3. socket 标识与端口号: 端口号是 socket 标识的一部分.

      • UDP 的 socket 标识是一个二元组:
      • TCP 的 socket 标识是一个四元组: < 源 IP, 目的 IP, 源端口, 目的端口 >
      • 为什么会有这个差异?
        • 简单来说:
          • tcp不管服务端还是客户端都是先建立连接(面向连接),所以socket上有双方的ip和端口,否则是非法。udp不需要建立连接,直接封装一个udp包(指定接收方ip和端口)就能发,非面向连接。所以tcp四元组才唯一标识一个socket连接,udp二元组(目的ip和目的端口)即可。
        • 我们知道TCP是面向连接的传输协议,所谓面向连接,是指数据在发送之前要在两台主机之间先建立好连接,在整个过程中要维护连接,最后要释放连接。
        • 如果TCP协议也使用二元组来标识套接字,那么就无法实现面向连接的特点。
        • 假设A和B两台主机同时请求一台服务器上的80端口,如果只使用目标IP和目标端口号,那么在服务器端只会创建一个套接字。显然TCP协议就无法维护A和B各自的序号、确认号、拥塞窗口等连接参数,这就违背了面向连接的设计。
        • 另外,面向连接使得TCP可以进行全双工通信,服务端只要将想发送的数据放入套接字即可向客户端发送信息。如果仅使用二元组来标识连接套接字,那么服务端就无法主动向客户端发送信息。
        • UDP使用二元组(目标IP和目标端口号)即可确定一个套接字,因为UDP不需要建立连接,而我们至少在IP地址的基础上还需要一个端口号才能实现运输层功能,而更多的内容对于UDP套接字来说也无必要。这也符合UDP的设计理念,即在网络层上附加尽可能少的功能。

    3.无连接传输UDP

    1. 网络层提供的服务(best-effort service):

      • 尽最大努力将数据包交付到目的主机
      • 不保证投递的可靠性和顺序
      • 不保证带宽及延迟要求
    2. UDP提供的服务

      • 进程到进程之间的报文交付
      • 报文完整性检查(可选):检测并丢弃出错的报文
    3. UDP需要实现的功能:

      • 多路复用与解复用
      • 报文检错

    3.1UDP报文结构

    1. UDP报文:
      • 报头:携带协议处理需要的信息
      • 载荷(payload):携带上层数据
    2. 用于多路复用/解复用的字段:
      • 源端口号,目的端口号
    3. 用于检测报文错误的字段:
      • 报文总长度
      • 检查和(checksum)

    3.2 UDP检查和(checksum

    1. 作用: 对传输的报文进行检错
    2. 发送方:
      • 将报文看成是由16比特整数组成的序列
      • 这些整数序列计算检查和
      • 将检查和放到UDP报文的checksum字段
    3. 接收方:
      • 对收到的报文进行相同的计算
      • 与报文中的checksum字段进行比较:
        • 不相等:报文有错误
        • 相等:认为没有错误
    4. UDP检查和计算
      • 计算UDP检查和包括伪头、UDP头和数据 三个部分。

      • 检查和的使用是可选的 ,若不计算检查和,该字段填入0。

      • 在这里插入图片描述

      • 计算检查和时,checksum字段填0

      • 接收方对UDP报文(包括检查和)及伪头求和,若结果为0xFFFF,认为没有错误

    3.3为什么需要UDP

    1. 应用可以尽可能快地发送报文:
      • 无建立连接的延迟
      • 不限制发送速率(不进行拥塞控制和流量控制)
    2. 报头开销小
    3. 协议处理简单
    4. UDP适合的应用:
      • 容忍丢包但对延迟敏感的应用:如流媒体
      • 以单次请求/响应为主的应用:如DNS
    5. 若应用要求基于UDP进行可靠传输:
      • 由应用层实现可靠性

    4.可靠数据传输

    1. 什么是可靠传输: 数据不会有比特损坏或丢失, 并按照发送的顺序被接收. 如何在不可靠的网络层上实现可靠的传输协议?
    2. Rdt协议:
      • Rdt 1.0 (理想信道)

        • 发送方只管发送,接收方只管接收
        • 下层信道是完全可靠的(理想情况)
          • 没有比特错误,没有分组丢失
        • 假设发送能力 ≤ 接收能力(不会出现来不及接收的现象)
        • 发送方和接收方的FSM均只有一个状态:
          • 发送方:从上层接收数据,封装成分组送入下层信道
          • 接收方:从下层信道接收分组,取出数据交给上层
        • 在这里插入图片描述
      • Rdt2.0(可能产生比特错误的下层信道)

        • 下层信道可能使分组中的比特产生错误(比特翻转)

          • 可以通过某种检错码(如checksum)检测比特错误
        • 问题:如何从错误中恢复?

          • 肯定确认(ACK): 接收方显式地告诉发送方,收到的分组正确
          • 否定确认(NAK): 接收方显式地告诉发送方,收到的分组有错
          • 重传:发送方收到NAK后,重传出错的分组
        • 与rdt1.0相比,rdt2.0中需要三种新的机制:

          • 接收方检错
          • 接收方反馈
          • 发送方重传分组
        • 在这里插入图片描述

        • ACK或NAK出错会怎样?

          • 发送方不清楚接收方发生了什么!
          • 常见的处理方法:发送方在收到出错的确认后,重传该分组(假设分组也出错了)
          • 问题:可能在接收端产生冗余分组
        • 如何处理冗余问题?

          • 发送方给每个分组添加一个序号
          • 接收方根据序号检测冗余的分组,并丢弃(不会交付给上层)
        • 分组序号的长度?

          • 如果前一个分组发送成功了再发送下一个分组,只需1个比特
      • 在这里插入图片描述

      • 在这里插入图片描述

      • Rdt 2.2 (有比特错误的信道)

        • 分组检错,使用分组序号,使用带序号的ACK
        • 不使用NAK的协议
        • 发送方/接收方未收到期待序号的ACK/分组时, 重传当前分组/ACK
        • rdt2.1也可以不用NAK,只用ACK
          • 让ACK携带所确认分组的序号
          • 接收方只对正确接收的分组发送ACK
          • 对于出错的分组,重发最近一次的ACK
      • 在这里插入图片描述

      • Rdt 3.0 (有比特错误和丢包的信道)

        • 增加新的假设:

          • 下层信道可能丢包(包括数据及ACK)
        • 需要两个新机制:

          • 检测丢包
          • 从丢包中恢复
        • 方法:

          • 检测丢包:
            • 若发送方在“合理的”时间内未收到ACK,认为丢包(需要定时器)
          • 从丢包中恢复:
            • 发送方重发当前分组
          • 问题:
            • ACK丢失或超时设置过短导致的重发,会在接收端产生冗余分组
            • 用分组序号解决
        • 分组检错,使用分组序号,使用带序号的ACK

        • 发送方定时器超时后重发分组

        • 接收方未收到期待序号的分组时,重发ACK

      • 在这里插入图片描述

      • 在这里插入图片描述

      • 小结

        • 在这里插入图片描述

    4.1可靠传输协议设计过程

    1. 不可靠信道有哪些出错类型:比特错误,丢包
    2. 如何发现错误:接收方通过检错码发现出错包,利用定时器发现丢失包
    3. 采取什么恢复措施:重传出错或丢失的包
    4. 恢复措施引入的问题:ACK出错、ACK丢失或超时设置过短,导致接收端出现冗余分组
    5. 如何解决冗余分组的问题:给分组加上序号,序号多长
    6. 将以上措施汇总,画出各种情形下的时间线图(正常,分组出错,ACK出错,分组丢失,ACK丢失,过早超时)
    7. 归纳发送方、接收方的事件类型及采取的动作,画出FSM

    4.2 流水线可靠数据传输协议

    1. rdt3.0是一种停-等(stop-and-wait)协议
      • rdt3.0是一个正确的协议,但性能不佳!
      • 流水线:提高链路利用率
    2. 流水线协议: 允许发送方有多个已发送、未确认的分组
      • 分组的序号范围应扩大(停等协议只使用1比特序号)
      • 发送端和接收端可能需要缓存多个分组(停等协议中,发送端缓存一个分组,接收端不缓存)
      • 两种基本的流水线协议: go-Back-N, selective repeat

    4.3Go-Back-N

    1. 收发规则:
      • Sender:
        • 最多允许N个已发送、未确认的分组
        • 对于最早的已发送、未确认的分组使用一个定时器
        • 若定时器超时, 从最早已发送、未确认的分组开始,顺序发送其后的分组
      • Receiver:
        • 每收到一个分组,都要发送一个带序号的ACK
        • 对于未按顺序到来的分组,丢弃,重发最近一次的ACK
        • 使用 累积确认: 若ACK包含序号q,表明“序号至q的分组均正确收到”
    2. 概念:
      • 已发送未确认序号 + 未发送可用序号 = 发送窗口(包含N个序号)
      • Ack分组携带所确认分组的序号
      • 使用累积确认: 若ACK包含序号q,表明“序号至q的分组均正确收到”
      • 若发送方收到ACK q,则更新基序号为 q+1,整体滑动发送窗口
      • 发送方只对基序号分组使用一个定时器
      • 超时:发送方重传发送窗口中从基序号开始的所有分组

    4.4 GBN的发送方

    1. 收到上层的发送请求
      • 若发送窗口满:拒绝请求
      • 若发送窗口不满:
        • 构造分组并发送(从下一个可用序号开始设置)
        • 若原来发送窗口为空:对基序号启动一个定时器
    2. 收到ACK q
      • 更新基序号为q+1
      • 若发送窗口变为空:终止定时器
      • 若发送窗口不空:对基序号启动一个定时器
    3. 收到出错的ACK
      • 不做处理,为什么?
        • 若ack p出错,可由后续收到的ack q(q>p)进行累积确认
        • 若ack p出错,且后续未收到ack,则超时后重传 pkt p
    4. 定时器超时
      • 启动定时器,从已发送未确认的分组开始,发送位于当前发送窗口内的所有分组

    GBN小结

    1. 接收端:
      • 按顺序接收分组,不缓存失序的分组
      • 按照累积确认的要求发送ACK
    2. 发送端:
      • 仅当发送窗口不满时,才能发送新的分组
      • 收到确认后,更新发送窗口
      • 当发送窗口发生变化(空<->非空,基序号更新)时,需要重新设置定时器
      • 超时后,重发发送窗口中的全部分组
    3. 特点:
      • 接收端简单,发送端复杂,出错后需要较多的重传

    5.选择重传(Selective Repeat)

    1. 要点:

      • 发送方仅重传它认为出错(未收到ACK)的分组,以避免不必要的重传
    2. 为此:

      • 接收端需缓存失序的分组
      • 接收端需对每个正确收到的分组单独确认(选择确认) (注意:选择重传不使用累积确认)
      • 发送的每个分组需要一个定时器,以便被单独重发

    5.1SR的发送窗口和接收窗口

    1. 发送窗口:
      • 包含“已发送未确认”和“未发送可用”的序号
      • 可能有“已发送已确认”的序号交织其中
      • 基序号是“已发送未确认”或“未发送可用”的序号
      • 收到基序号的ACK时,滑动发送窗口
    2. 接收窗口:
      • 包含“期待但未收到”和“允许接收”的序号
      • 可能有“已确认已缓存”的序号交织其中
      • 基序号为“期待但未收到”或“允许接收”的序号
      • 收到基序号分组时,按顺序交付分组,滑动接收窗口

    5.2选择重传的工作过程

    1. 发送方:
      • 从上层接收数据:
        • 若发送窗口未满,发送分组,启动定时器
      • 定时器 n 超时:
        • 重传分组n, 重启定时器
      • 收到发送窗口内的ACK(n) :
        • 标记分组n为已确认
        • 若n=基序号,滑动发送窗口,使基序号=最小未确认的序号或下一个序号
      • 其余情形:
        • 忽略
    2. 接收方:
      • 收到接收窗口内的分组n:
        • 发送ACK(n)
        • 若为失序分组:缓存该分组
        • 若n=基序号:交付从n开始的若干连续分组;滑动接收窗口,使基序号=下一个期待接收的序号
      • 收到[rcvbase-N,rcvbase-1]内的分组n
        • 发送ACK(n)
      • 其余情形:
        • 忽略
      • 接收方在收到[[rcvbase-N,rcvbase-1]内的分组n,为什么要发送ACK n?
        考虑以下情形:发送方发送了一个满窗口([0,N-1])的分组;接收方全都接收正确,发送了ACK,并滑动接收窗口至[N,2N-1] ,但其中有分组没有被正确接收,发送端超时后重发该分组。如果接收端不响应这个分组,那发送方的发送窗口将不能更新,发送停滞。

    5.3 选择重传:窗口大小和序号空间的关系

    1. 选择重传:通常发送窗口大小 = 接收窗口大小
    2. 考虑以下情形:发送方发送了一个满窗口([0,N-1])的分组;接收方全都接收正确,发送了ACK,并滑动接收窗口至[N,2N-1] 。但N个ACK全都没有正确接收,发送端超时后逐个重发这N个分组
      • 为使发送端能够移动发送窗口,接收端必须对[0,N-1]中的分组进行确认,这回答了接收方为什么需要对[rcvbase-N, rcvbase-1](前一个满窗口)中的分组进行确认
      • 为使接收端不会将重发的分组当成新的分组,窗口[0,N-1]和窗口[N,2N-1]不能重叠,即N+N≤K(序号空间)。所以,N不能大于序号空间的一半

    小结

    1. 接收端:
      • 落在接收窗口中的分组都要接收,每个分组单独确认
      • 尽管允许乱序接收,但仍须按顺序交付数据
    2. 发送端:
      • 发送窗口不满时可以发送新的分组
      • 每个已发送的分组都需要一个定时器
      • 若定时器n超时,只重发序号为n的分组
    3. 特点:
      • 出错后重传代价小,发送端使用较多定时器,接收端需要较大缓存,实现复杂
    4. 梳理流水线机制的设计
      • 一次允许发送多个包会带来什么新的问题:
        • 序号长度k,窗口大小N和k有什么关系,发现分组出错或丢失怎么处理
      • GBN:一旦发现出错后,接收方不再接收新的包,双方从出错的包开始重新发送和接收
      • SR:发现出错后,接收方可以继续接收落在接收窗口内的包,过后仅发送/接收出错的包
      • 画出GBN和SR的时间线图,据此画出FSM

    6.面向连接的传输:TCP

    6.1序号和确认序号

    1. 序号:
      • 报文段中第一个数据字节的序号
    2. 确认序号:
      • 使用累积确认,指出期望从对方接收的下一个字节的序号
      • 确认号就是接收方期待的下一个字节序号
      • 确认号对于 TCP 超时设置的作用:
        • 估计 RTT: 测量从发出某个报文段到收到其确认之间经过的时间, 作为 SampleRTT.
    3. Q: 接收方如何处理失序的报文段?
      • A: TCP规范未涉及,留给实现者考虑
    4. 举例
      • 在这里插入图片描述

    6.2TCP超时设置

    1. 如何设置TCP超时值?
      • 超时值太小:
        • 产生不必要的重传
      • 超时值太大:
        • 丢失恢复的时间 太长
      • 应大于RTT:
        • RTT是变化的
    2. Q: 如何估计RTT?
      • SampleRTT:
        • 测量从发出某个报文段到收到其确认报文段之间经过的时间
      • SampleRTT是变化的,更有意义的是平均RTT

    6.3 估算平均RTT

    1. EstimatedRTT = (1- α)*EstimatedRTT + α*SampleRTT \text{EstimatedRTT = (1- α)*EstimatedRTT + α*SampleRTT} EstimatedRTT = (1- α)*EstimatedRTT + α*SampleRTT
      • 指数加权移动平均
      • 典型值: α = 0.125
      • 瞬时RTT和平均RTT有很大的偏差
      • 应当在EstimtedRTT 加上一个“安全距离”,作为超时值
      • 安全距离的大小与RTT的波动幅度有关

    6.4 设置超时值

    1. SampleRTT 与 EstimatedRTT的偏差估计:
      • 在这里插入图片描述
    2. 设置超时值:
      • 在这里插入图片描述

    6.5 TCP可靠数据传输

    1. TCP 在不可靠的IP服务上建立可靠的数据传输
    2. IP层信道:IP包可能出错、丢失、重排序
    3. TCP采用的数据传输机制
      • 发送端采用流水式发送报文段
      • 接收端采用累积确认进行响应
      • 发送端采用重传来恢复丢失的报文段

    6.6 一个高度简化的TCP协议

    1. 仅考虑可靠传输机制,且数据仅在一个方向上传输
      • 接收方:
        • 仅在正确、按序收到报文段后,更新确认序号;其余情况,重复前一次的确认序号(与GBN类似,使用累积确认)
        • 缓存失序的报文段(与SR类似)
      • 发送方:
        • 流水式发送报文段
        • 仅对最早未确认的报文段使用一个重传定时器(与GBN类似)
        • 仅在超时后重发最早未确认的报文段(与SR类似,接收端缓存了失序的报文段)

    6.7TCP发送方处理的事件

    1. 收到应用数据:
      • 创建并发送TCP报文段
      • 若当前没有定时器在运行(没有已发送、未确认的报文段),启动定时器
    2. 超时:
      • 重传包含最小序号的、未确认的报文段
      • 重启定时器
    3. 收到ACK:
      • 如果确认序号大于基序号:
        • 推进发送窗口(更新基序号)
        • 如果还有未确认的报文段,启动时器,否则终止定时器

    6.8快速重传

    1. 仅靠超时重发丢失的报文段,恢复太慢!
    2. 利用重复ACK检测报文段丢失:
      • 发送方通常连续发送许多报文段
      • 若报文段丢失,会有许多重复ACK发生
      • 多数情况下IP按序交付分组,重复ACK极有可能因丢包产生
    3. 协议规定:当发送方收到对同一序号的3次重复确认时,立即重发包含该序号的报文段
    4. 快速重传: 在定时器到期前重发丢失的报文段

    小结

    1. 可靠传输的设计:
      • 流水式发送报文段
      • 采用累积确认
      • 只对最早未确认的报文段使用一个重传定时器
      • 超时后只重传包含最小序号的、未确认的报文段
      • 以上措施可大量减少因ACK丢失、定时器过早超时引起的重传
    2. 超时值的确定:
      • 基于RTT估计超时值+ 定时器补偿策略
    3. 测量RTT:
      • 不对重传的报文段测量RTT
      • 不连续使用推迟确认
    4. 快速重传:
      • 收到3次重复确认,重发报文段

    6.9TCP与GBN/SR对比

    1. Go-Back-N

      • 接收方:
        • 使用累积确认
        • 不缓存失序的分组
        • 对失序分组发送重复ACK
      • 发送方:
        • 超时后重传从基序号开始的所有分组
    2. TCP

      • 接收方:
        • 使用累积确认
        • 缓存失序的报文段
        • 对失序报文段发送重复ACK
      • 发送方:
        • 超时后仅重传最早未确认的报文段
        • 增加了快速重传
    3. SR

      • 接收方:
        • 缓存失序的分组
        • 每个分组使用一个定时器
        • 单独确认每个正确收到的分组
      • 发送方:
        • 超时后仅重传未被确认的分组
    4. 修改的TCP [RFC2018]

      • 接收方:
        • 缓存失序的报文段
        • 只对最早未确认的报文段使用一个定时器
        • SACK选项头中给出收到的非连续数据块的上下边界
      • 发送方:
        • 仅重传接收方缺失的数据
        • 增加了快速重传

    6.10TCP结合了GBN和SR的优点

    1. TCP的可靠传输机制可以看成是 GBN和SR的混合体:
      • 定时器的使用:与GBN类似,只对最早未确认的报文段使用一个定时器
      • 超时重传:与SR类似,只重传缺失的数据
    2. TCP在减小定时器开销和重传开销方面要优于GBN 和 SR!

    7.TCP流量控制

    1. 问题:
      • 进入接收缓存的数据不一定被立即取走、取完
      • 若应用消费数据的速度较慢,接收缓存可能溢出
    2. 流量控制:
      • 发送端TCP调节发送速率,不使接收端缓存溢出
    3. 为什么GBN或SR不考虑流量控制
      • GBN和SR均假设:
        • 正确、按序到达的分组被立即交付给上层
        • 其占用的缓冲区被立即释放
      • 从而,GBN和SR不会出现接收端缓存溢出的问题
    4. 为什么UDP没有流量控制:
      • UDP不保证交付:
        • 接收端UDP将收到的报文载荷放入接收缓存
        • 应用进程每次从接收缓存中读取一个完整的报文载荷
        • 当应用进程消费数据不够快时,接收缓存溢出,报文数据丢失,并不违反UDP的服务承诺

    7.1接收窗口

    1. 接收缓存中的可用空间称为接收窗口(RcvWindow)
      在这里插入图片描述
      • 接收方将RcvWindow放在报头中,向发送方通告接收缓存的可用空间
      • 发送方限制未确认的字节数不超过接收窗口的大小,即:在这里插入图片描述

    7.2零窗口通告和零窗口探测

    1. 特别是,发送端收到RcvWindow = 0的报文段(零窗口通告)时,必须停止发送,然后:
      • 发送端启动一个定时器
      • 定时器超时后,发送端发送一个零窗口探测报文段(序号为上一个段中最后一个字节的序号)
      • 接收端在响应的报文段中通告当前的接收窗口
      • 若发送端仍收到零窗口通告,重新启动定时器

    说明:零窗口探测的唯一作用是触发接收端发送响应

    7.3糊涂窗口综合症(silly window syndrome)

    1. 当数据发送很快、而消费很慢时,零窗口探测的简单实现带来以下问题:
      • 接收方不断发送微小窗口通告
      • 发送方不断发送很小的数据分组
      • 大量带宽被浪费
    2. 接收端避免糊涂窗口综合症的策略:
      • 通告零窗口之后,仅当窗口大小显著增加之后才发送更新的窗口通告
      • 什么是显著增加:窗口大小达到缓存空间的一半或者一个MSS,取两者的较小值
    3. TCP执行该策略的做法:
      • 当窗口大小不满足以上策略时,推迟发送确认(但最多推迟500ms,且至少每隔一个报文段使用正常方式进行确认),寄希望于推迟间隔内有更多数据被消费
      • 仅当窗口大小满足以上策略时,再通告新的窗口大小
    4. 发送方避免糊涂窗口综合症的策略:
      • 发送方应积聚足够多的数据再发送,以防止发送太短的报文段
      • 问题:发送方应等待多长时间?
        • 如等待时间不够,报文段会太短
        • 如等待时间过久,应用程序的时延会太长
        • 更重要的是,TCP不知道应用程序会不
        • 在最近的将来生成更多的数据

    小结

    1. TCP接收端:
      • 使用显式的窗口通告告知发送方可用的缓存空间大小
      • 在接收窗口较小时推迟发送确认(条件允许的话)
      • 在零窗口通告后,仅当接收窗口显著增加时通告新的窗口大小
    2. TCP发送端:
      • 使用Nagle算法确定发送时机
      • 使用接收窗口限制发送的数据量(已发
      • 未确认的字节数不超过接收窗口的大小)

    8.连接管理

    1. 建立连接要确定两件事:
      • 双方都同意建立连接(知晓另一方想建立连接)
      • 初始化连接参数(序号,MSS等)

    8.1TCP三次握手

    在这里插入图片描述

    1. Step 1: 客户TCP发送SYN 报文段
      (SYN=1, ACK=0)
      • Seq = 客户的起始序号
      • Ack:无有效内容
      • 不包含数据
    2. Step 2: 服务器TCP发送SYNACK报文段(SYN=ACK=1)
      • Seq = 服务器的起始序号
      • Ack = 客户起始序号+1
      • 不包含数据(服务器端分配缓存和变量)
    3. Step 3: 客户发送ACK报文段(SYN=0,ACK=1)
      • Seq =客户起始序号+1
      • Ack = 服务器起始序号+1
      • 可以包含数据(客户端分配缓存和变量)

    8.2起始序号

    1. 为什么起始序号不从1开始?

      • 若每个新建连接都从序号1开始,那么在不同时间、同一对套接字之间建立的连接,它们的握手报文段都一样,且旧连接上的报文段可能会干扰新连接上的传输(报文段序号有重叠)
    2. 可以随机选取起始序号吗?

      • 新、旧连接上报文段序号重叠的可能性将大为减小,但不能完全避免
    3. 必须避免新、旧连接上的序号产生重叠

    4. 基于时钟的起始序号选取算法:

      • 每个主机使用一个时钟,以二进制计数器的形式工作,每隔ΔT时间,计数器加1
      • 新建一个连接时,以计数器值的最低32位作为起始序号
      • 该方法确保连接的起始序号随时间单调增长
    5. 取较小的ΔT,确保起始序号的增长速度超过TCP连接上序号的增长速度

    6. 使用较长的序号(32位),确保序号回绕的时间远大于分组在网络中的最长寿命

    8.3关闭连接

    在这里插入图片描述

    • 关闭连接: 四次挥手

    9.拥塞控制

    1. 交通拥堵(类比的例子):
      • 起因:大量汽车短时间内进入路网,超出路网的承载能力
      • 表现:道路通行能力下降,车速变慢,甚至完全停滞
      • 措施:减少车辆进入(交通管制)
    2. 网络拥塞:
      • 起因:大量分组短时间内进入网络,超出 网络的处理能力
      • 表现:网络吞吐量下降,分组延迟增大
      • 措施:减少分组进入网络(拥塞控制)
    3. 流量控制与拥塞控制:
      • 流量控制:限制发送速度,使不超过接收端的处理能力
      • 拥塞控制:限制发送速度,使不超过网络的处理能力

    9.1流量控制与拥塞控制区别

    • 流量控制是端到端的控制
      • 例如A通过网络给B发数据,A发送的太快导致B没法接收(B缓冲窗口过小或者处理过慢),这时候的控制就是流量控制
      • 原理是通过滑动窗口的大小改变来实现。
    • 拥塞控制是A与B之间的网络发生堵塞导致传输过慢或者丢包,来不及传输。
      • 防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。
      • 拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络性能有关的所有因素。

    9.2 网络拥塞的代价

    1. 延迟增大

      • 拥塞发生在路由器中:
        • 对于路由器的某条输出链路而言,当进入该链路的数据速率接近或超出链路带宽时,就会发生拥塞
      • 代价一:分组延迟增大
        • 即使不考虑丢包(假设有无限大的缓存),当链路接近满载时,排队延迟急剧增大
    2. 吞吐量下降

      • 场景一:
        • 路由器输出缓存溢出,发送端TCP重传被丢弃的包
        • 在这里插入图片描述
      • 场景二:
        • 发送端定时器过早超时,产生了不必要的重传
        • 在这里插入图片描述

    9.3拥塞控制方法

    1. 端到端拥塞控制:

      • 网络不向端系统提供显式反馈
      • 端系统通过观察丢包和延迟来推断拥塞的发生,进而降低发送速率
      • TCP采用此类方法
    2. 网络辅助的拥塞控制:

      • 发生拥塞的路由器向相关的发送端/接收端提供直接反馈,指示拥塞 程度或直接给出发送速率
      • 发送端相应降低发送速率
      • TCP ECN, ATM, DECbit协议采用此方法

    9.4TCP拥塞控制

    1. TCP使用端到端拥塞控制机制:
      • 发送方根据自己感知的网络拥塞程度,限制其发送速率
    2. 发送方如何感知拥塞?
      • 利用丢包事件感知拥塞
        • 丢包或分组延迟过大,对于发送端来说都是丢包了
      • 丢包事件包括:
        • 超时
        • 3次重复的ACK
    3. 发送方调节拥塞窗口的策略
      • 加性增、乘性减
      • 慢启动
    4. 发送方使用拥塞窗口CongWin限制已发送未确认的数据量:
    • 在这里插入图片描述
    • CongWin随所感知的网络拥塞程度而变化

    9.5加性增、乘性减(AIMD)

    1. 乘性减:每检测到一个丢包事件,CongWin减半(迅速减小),但不能小于一个MSS
    2. 加性增: 若没有丢包,每经过一个RTT,CongWin增大一个MSS(缓慢增大),直到检测到丢包
      在这里插入图片描述

    9.6慢启动

    1. 连接刚建立时
      • CongWin = 1 MSS
    2. 按照加性增来增大CongWin:
      • 每隔一个RTT才能增大一个MSS,速度太慢!
    3. 希望迅速增大CongWin至可用的发送速度
    4. 基本思想:
      • 新建连接上指数增大CongWin,直至检测到丢包(此时终止慢启动过程)

    9.6.1慢启动的实施

    1. 慢启动的策略:
      • 每经过一个RTT,CongWin加倍
    2. 具体实施方法:
      • 每收到一个ACK段,CongWin增加一个MSS
    3. 特点:
      • 以一个很低的速率开始,按指数增大发送速率

    9.7区分不同的丢包事件

    1. 丢包事件:
      • 收到3个冗余ACK:说明网络仍有一定的交付能力
      • 超时:说明网络交付能力很差
    2. 目前的TCP实现区分不同的丢包事件
    3. 收到3个冗余ACK
      • CongWin降为一半
      • 采用AIMD调节
    4. 超时
      • CongWin = 1MSS
      • 使用慢启动增大CongWin,至 超时发生时CongWin的一半
      • 使用AIMD调节

    9.7.1 实现

    1. 发送方维护一个变量Threshold
    2. 发生丢包时,Threshold设置为当前CongWin的一半
      • 若收到3次重复的ACK:令 CongWin = Threshold+3*MSS,执行AIMD(已有3个报文段到达接收端,不再占用网络资源,扩大CongWin以允许再发送3个报文段)
      • 若发生的是超时:CongWin = 1*MSS,执行慢启动
    3. Threshold是从慢启动转为拥塞避免的分水岭:
      • CongWin低于门限:执行慢启动
      • CongWin大于等于门限:执行AIMD(也称拥塞避免

    在这里插入图片描述

    • 为什么在收到3个冗余ACK后,设置CongWin=threshold+3MSS?
      • CongWin的本意是用来限制正在网络中传输(in-flight)的数据量
      • 发送端使用公式LastByteSent -LastByteAcked ≤CongWin来执行该限制条件,在收到3个冗余的ACK时,说明有3个失序的报文段已经离开网络到达了接收端,从而发送端可以再发3个报文段
      • 但是由于采用累积确认不能更新LastByteAcked,以上公式限制再发送,所以直接在CongWin上加3个MSS,临时扩大拥塞窗口。
    • 举例说明:
      • 假设当前拥塞窗口cwnd=400bytes,MSS=100bytes,发送方发送了4个报文段,发送窗口中的字节序号为101~500,此时lastbytesent=500, lastbyteacked=100, lastbytesent-lastbyteacked = 400 = cwnd,不能再发送。
      • 假设第1个报文段丢失,后续3个报文段都到达接收端,则接收端会发送3个ACK 100的报文段。
        发送端收到3个重复的ack 100后,重发第1个报文段,并令threshold=cwnd/2=200bytes。若设置cwnd=threshold=200bytes, 此时因为lastbytesent - lastbyteacked = 400 > cwnd,发送端不能再发送了。
        - 但实际上,在当前的发送窗口中,第2~4个报文段已经到达接收端,它们不再占用网络资源,当前仍然在网络中传输的(已发送未确认的)只有第1个报文段,按照cwnd=200bytes,网络是有能力再传输一个报文段的。
    • 如何能让发送端再发送一个报文段呢?
      • 由于基序号未确认不能滑动窗口,我们只能通过增大窗口来允许发送端发送更多的数据。
      • 若cwnd = threshold + 3MSS = 500bytes,则除了已经发送的4个报文段外,发送端还可以发送一个报文段(字节序号501~600),此时lastbytesent - lastbyteacked = 600 -100 = 500 = cwnd,并不违反拥塞窗口的限流要求。

    状态图

    在这里插入图片描述

    小结

    1. 当CongWin < Threshold时,发送方处于慢启动阶段, 拥塞窗口指数增长
    2. 当CongWin >= Threshold时,发送方处于拥塞避免阶段, 拥塞窗口线性增长
    3. 当收到3个冗余ACK 时, Threshold = CongWin/2, CongWin = Threshold + 3MSS(快速恢复)
    4. 超时发生时, Threshold = CongWin/2 , CongWin =1 MSS

    9.8 TCP吞吐量

    1. 一个长期存活的TCP连接的平均吞吐量是多少?(忽略慢启动阶段)

      • 令W=发生丢包时的CongWin,此时
        throughput = W/RTT

      • 发生丢包后调整 CongWin=W/2,此时throughput=W/2RTT

      • 假设在TCP连接的生命期内,RTT 和 W几乎不变,则:Average throughout=0.75 W/RTT

    2. Example: 1500 byte segments, 100ms RTT, want 10 Gbps throughput

      • 根据平均吞吐量公式,平均拥塞窗口(0.75W)= 83,333 报文段

      • 一条TCP连接的平均吞吐量与丢包率L的关系(课后习题):在这里插入图片描述

      • L = 2 ∗ 1 0 − 10 L =2*10^{-10} L=21010

      • 针对高速网络需要新的TCP拥塞控制算法

    9.9TCP的公平性

    1. 公平性目标:
      • 如果K条TCP连接共享某条带宽为 R R R的瓶颈链路,每条连接具有平均速度 R / K R/K R/K
    2. TCP公平性更复杂的情形
      • 若相互竞争的TCP连接具有不同的参数(RTT、MSS等),不能保证公平性;
      • 若应用(如web)可以建立多条并行TCP连接,不能保证带宽在应用之间公平分配;比如,一条速率为R的链路上有9条连接:
        • 若新应用建立一条TCP连接,获得速率 R/10
        • 若新应用建立11条TCP,可以获得速率 R/2 !

    9.10 关于TCP和UDP的思考

    1. 能否说TCP服务优于UDP服务?

      • 不同应用对传输层服务有不同的需求,适合的就是好的,所以不存在哪个服务绝对的好、或绝对的不好。
    2. 多媒体应用希望的传输层服务是:带宽有保证,延迟有保证,顺序有保证,但能忍受一些丢包。TCP或UDP能够满足多媒体应用的需求吗?

      • 根据多媒体应用希望的传输层服务,显然 TCP或UDP都不能完全满足。

    小结

    1. 传输服务原理:
      • 多路复用、解复用
      • 可靠数据传输
      • 流量控制
      • 拥塞控制
    2. Internet中的传输服务:
      • UDP
      • TCP

    例题

    1. 是非判断题:
      1)假设主机A通过一条TCP连接向主机B发送一个大文件,如果某个报文段的序号为m,则其后续报文段的序号必定是m+1。 ( × )
      2)假设主机A通过一条TCP连接向主机B发送一个序号为38、包含4个数据字节的报文段,则主机B对该报文段的确认号必定是42。 ( × )
      3)假设主机A通过一条TCP连接向主机B发送一个大文件,主机A已发送但未被确认的字节数不会超过接收缓存的大小。 ( √ )
      4)在TCP连接的持续过程中,TCP头中的rwnd不会变化。 ( × )

    2. 假设主机A通过一条TCP连接向主机B发送两个紧接着的TCP报文段。第一个报文段的序号为80,第二个报文段的序号为120。请问:
      1)第一个报文段中有多少数据?
      120 - 80 = 40 bytes
      2)假设第一个报文段丢失,而第二个报文段到达主机B。那么在主机B发往主机A的确认报文中,确认号应该是多少?
      80

    3. 发送方TCP的基序号SendBase和接收方缓存中的LastByteRcvd之间的关系为
      (A) LastByteRcvd ≧ SendBase-1
      (B) LastByteRcvd ≧ SendBase
      (C) 不能确定

    4. 假设发送方TCP收到了确认序号y(表示y之前的字节均已正确收到),则y与接收方缓存中的LastByteRcvd之间的关系为
      (A) LastByteRcvd = y-1
      (B) LastByteRcvd ≧ y-1
      ( C) 不能确定

    5. 主机A向主机B发起一个TCP连接,假设主机A和主机B选择的起始序号分别为70和90,将下表中三次握手交换的报文段的相关信息填充完整。

      报文段SYN flagACK flagSeq numberAck number
      11070
      2119071
      3017191
    6. TCP用于流量控制的窗口是 接收窗口 ,用于拥塞控制的窗口是 拥塞窗口

    7. 假设主机A在一条TCP连接上发送了一大批数据,然后在t1时刻变得空闲(因为没有更多的数据需要发送)。在相对较长的一段时间空闲后,在t2时刻又有一大批数据需要发送。你认为此时主机A应当使用t1时刻的CongWin和Threshold,还是应当使用慢启动发送数据?为什么?

      答:应使用慢启动发送数据。从题意来看,t1时刻的CongWin和Threshold可能较大。经过了相对较长的一段时间后,网络状态可能发生了变化,此时应使用慢启动逐渐提高发送速度,以免一下子发送大量数据引起网络拥塞。

    8. 传输层最基本的功能是?
      A. 流量控制
      B. 拥塞控制
      C. 实现不同主机的进程间通信
      D.可靠传输

    9. TCP 确认报文段被用于确认已收到的报文段、检测丢失的报文段、调整超时定时器的设置, 简要说明 TCP 报文段是如何发挥以上作用的

      • 确认已收到的报文段:
        • TCP的报文到达确认(ACK),是对接收到的数据的最高序列号的确认,并向发送端返回一个下次接收时期望的TCP数据包的序列号(Ack Number)。例如,主机A发送的当前数据序号是400,数据长度是100,则接收端收到后会返回一个确认号是501的确认号给主机A。
        • 同时,TCP的确认机制,也可以一次确认多个数据报(累积确认),例如,接收方收到了201,301,401的数据报,则只需要对401的数据包进行确认即可,对401的数据包的确认也意味着401之前的所有数据包都已经确认,这样也可以提高系统的效率。
      • 检测丢失的报文段:
        • 除了通过对最早未确认的报文段设置一个定时器,通过检测是否超时来检测丢失报文段以外,还可以通过利用重复ACK检测报文段丢失:
        • 发送方通常连续发送许多报文段、若报文段丢失,因为接收方的确认报文是对期待收到的下一个报文的确认号,所以如果某一报文丢失,则会有许多重复ACK发生、多数情况下IP按序交付分组,重复ACK极有可能因丢包产生
        • 协议规定:当发送方收到对同一序号的3次重复确认时,立即重发包含该序号的报文段
      • 调整超时定时器:
        • 仅对最早未确认的报文段使用一个重传定时器(与GBN类似)
        • 仅在超时后重发最早未确认的报文段(与SR类似,接收端缓存了失序的报文段)
        • 重传定时器:为了控制丢失的报文段或丢弃的报文段,也就是对报文段确认的等待时间。当TCP发送报文段时,就创建这个特定报文段的重传计时器,可能发生两种情况:若在计时器超时之前收到对报文段的确认,则撤销计时器;若在收到对特定报文段的确认之前计时器超时,则重传该报文,并把计时器复位;
        • 重传时间=2*RTT;
        • RTT的值应该动态计算。常用的公式是: RTT=0.875*previousRTT+0.125*currentRTT \text{RTT=0.875*previousRTT+0.125*currentRTT} RTT=0.875*previousRTT+0.125*currentRTT。即新的RTT是以前的RTT值的0.875加上当前RTT值的 0.125.

    TCP数据包中的序列号(Sequence Number)不是以报文段来进行编号的,而是将连接生存周期内传输的所有数据当作一个字节流,序列号就是整个字节流中每个字节的编号。一个TCP数据包中包含多个字节流的数据(即数据段),而且每个TCP数据包中的数据大小不一定相同。在建立TCP连接的三次握手过程中,通信双方各自已确定了初始的序号x和y,TCP每次传送的报文段中的序号字段值表示所要传送本报文中的第一个字节的序号。

    在这里插入图片描述

  • 相关阅读:
    Nacos Discovery--服务治理
    Kotlin学习笔记(八)by的作用,属性委托和类的委托,和Lazy的关系
    自监督学习和对比学习举例讲解(附代码)
    选择SSL证书的理由以及优势
    CleanMyPC中文版切换教程(专注于电脑缓存文件清理的工具)
    202206 集合 面试
    算法中出现的一些报错及其处理办法
    008:连续跌三天,买第四天上涨的盈利计算
    Nacos 2.2.3 部署到linux
    信息系统项目管理师 第四版 口诀
  • 原文地址:https://blog.csdn.net/weixin_56462041/article/details/127821221