type
slug
status
summary
icon
category
date
tags
password

3.0 传输层

notion image

3.1 概述和传输层服务

3.1.1 传输服务和协议

传输层层提供的服务:进程与进程间以(message)为单位的逻辑通信
  • 为运行在不同主机上的应用进程提供逻辑通信
  • 传输协议运行在端系统
    • 发送方:将应用层的报文分成报文段,然后传递给网络层
    • 接收方:将报文段重组成报文,然后传递给应用层
  • 有多个传输层协议可供应用选择
    • Internet: TCP和UDP
 
传输层 vs. 网络层
  • 网络层服务:主机到主机的逻辑通信
  • 传输层服务:进程到进程的逻辑通信
    • 依赖于网络层的服务
      • 延时、带宽
    • 并对网络层的服务进行增强
      • 数据丢失、顺序混乱、加密
    • 有些服务是可以加强的:不可靠 -> 可靠:安全
    • 但有些服务是不可以被加强的:带宽、延迟
 

3.1.2 传输层协议

  • 可靠的、保序的传输:TCP
    • Transmission Control Protocol
    • 数据报
    • 多路复用、解复用
    • 拥塞控制
    • 流量控制
    • 建立连接
  • 不可靠、不保序的传输:UDP
    • User Datagram Protoco
    • 字节流
    • 多路复用、解复用
    • 没有为尽力而为的IP服务添加更多的其它额外服务
  • 都不提供的服务:
    • 延时保证
    • 带宽保证
    • 这个依赖于网络层,是不可更改的特性
 
 

3.2 多路复用与解复用

notion image
TCP:往下传的是socket和message,源端口、目标端口+messege向下传
网络层(段):加上原IP和目标IP
notion image
UDP:向下传的是message,socket(源IP,源Port),目标IP和目标Port
notion image
 
 

3.2.1 多路解复用工作原理

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

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

  • 创建套接字:
    • 服务器端:serverSocket=socket(PF_INET, SOCK_DGRAM,0);
    • 客户端:clientSocket=socket(PF_INET, SOCK_DGRAM,0);
    • 没有bind,clientSocket和os为之分配的某个端口号捆绑,客户端使用什么端口号无所谓,客户端主动找服务器
  • 接收端UDP套接字用二元组标识(目标IP地址、目标端口号)
  • 当主机收到UDP报文段?
    • 检查报文段的目标端口号
    • 用该端口号将报文段定位给套接字
  • 如果两个不同源IP地址/源端口号的UDP数据报,但是有相同的目标IP地址和端口号,则被定位到相同的套接字
notion image
 
无连接的多路解复用
  • 回顾:创建拥有本地端口号的套接字
    • DatagramSocket mySocket1 = new DatagramSocket(12534);
  • 回顾:当创建UDP端采用的端口号可以指定
    • 目标IP地址
    • 目标端口号
  • 当主机接收到UDP段时:
    • 检查UDP段中的目标端口号
    • 将UDP段交给目标端口号的套接字
  • 如果两个不同源IP地址/源端口号的UDP数据报,但是有相同的目标IP地址和端口号,则被定位到相同的套接字
notion image
notion image
 

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

  • TCP套接字:四元组本地标识:
    • 源IP地址
    • 源端口号
    • 目的IP地址
    • 目的端口号
  • 解复用接收主机用这四个值来将数据报定位到合适的套接字
  • 服务器能够在一个TCP端口上同时支持多个TCP套接字
    • 每个套接字由其四元组标识(有不同的源IP和源PORT)
  • Web服务器对每个连接客户端有不同的套接字(源IP和源Port不同)
    • 非持久对每个请求有不同的套接字
notion image
 
notion image
这个图的表项是有点问题的,比如说P1,SIP=A….
notion image

3.3 无连接传输UDP

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

3.3.1 UDP: 用户数据报协议

  • 为什么要有UDP?
    • 不建立连接(会增加延时)
    • 简单:在发送端和接收端没有连接状态
    • 报文段的头部很小(开销小,头部只有8个字节,TCP头部可能20个字节)(载荷:有效的传输部分)
    • 无拥塞控制和流量控制:UDP可以尽可能快的发送报文段
      • 应用->传输的速率=主机->网络的速率
  • 数据报
 
notion image

3.3.2 UDP校验和

  • 目标:检测在被传输报文段中的差错(如比特反转)检测整个报文段
  • 出错表示为message丢失
  • 发送方:
    • 将报文段的内容视为16比特的整数
    • 校验和:报文段的加法和(1的补运算)
    • 发送方将校验和放在UDP的校验和字段
  • 接收方:
    • 计算接收到的报文段的校验和
    • 检查计算出的校验和与校验和字段的内容是否相等:
      • 不相等---检测到差错
      • 相等---没有检测到差错,但也许还是有差错
        • 残存错误
notion image
在接收方,同样将需要校验部分的数据按16比特分成多个单元,对各个单元同样采用求和累加(高位溢出到低位再相加),再加上校验和,然后检查得到的结果,如果是全1则传输无误(有的实现可能对得到的和会取反码,然后判断最终值是不是全0)。
notion image

3.4 可靠数据传输

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

  • rdt在应用层、传输层和数据链路层都很重要
  • 是网络Top 10问题之一
    • notion image
      上层的用户称为应用层的process,
  • 信道的不可靠特点决定了可靠数据传输协议(rdt)的复杂性(向上层提供可靠的服务,下层提供的服务不可靠。在本层通过什么协议和资源从而实现向上层提供的可靠服务)
可靠数据传输:问题描述
  • rdt_send():被上层(如应用层)调用,以将数据交付给下层实体
  • udt_send():被rdt调用,用以将分组放到不可靠的信道上传输到接收方
  • udt_recv():当分组通过信道到达接收方时被调用
  • deliver_data():被rdt调用,将数据交付给上层实体
两个udt是本层rdt实体和和下层的原语/接口
notion image
 
  • 我们将:
    • 渐增式地开发可靠数据传输协议(rdt)的发送方和接收方
      • 依次去掉对下层通道的假设,通过增加协议间的内容来弥补通道性能的缺少
    • 只考虑单向数据传输
      • 但控制信息是双向流动的!
    • 双向的数据传输问题实际上是2个单向数据传输问题的综合
    • 可使用有限状态机(FSM)来描述发送方和接收方(有节点和边,边上是事件)
notion image

3.4.2 Rdt1.0:在可靠信道上的可靠数据传输

  • 下层的信道是完全可靠的
    • 没有比特出错
    • 没有分组丢失
  • 发送方和接收方的FSM
    • 发送方将数据发送到下层信道
    • 接收方从下层信道接收数据
notion image
 
发送方:接收数据单元,packet封装,通过下层接口打出去
本层协议的实现是为了给上层提供更好的服务。依靠下层的服务。所以一定有上层的原语调用,下层的服务调用。
接收方:等待下面的packet,然后解封装,然后通过层间接口给上层
 
 

3.4.3 Rdt2.0:具有比特差错的信道(差错检验ACK和NAK,重发)

  • 下层信道可能会出错:将分组中的比特翻转
    • 校验和检测比特差错
  • 问题:怎样从差错中恢复
    • 确认(ACK):接收方显式地告诉发送方分组已被正确接收
    • 否定确认(NAK):接收方显式地告诉发送方分组发生了差错
      • 发送方收到NAK后,发送方重传分组
  • rdt2.0中的新机制:采用差错控制编码进行差错检测
    • 发送方差错控制编码、缓存
    • 接收方使用编码检错
    • 接收方反馈控制报文(ACK, NAK):接收方→发送方
    • 发送方收到反馈相应的动作
notion image
虚线代表初始化
notion image
 

3.4.4 rdt2.1(ACK/NAK出错,序号重传和停等协议)

rdt2.0的致命缺陷! rdt2.1
  • 如果ACK/NAK出错?
    • 发送方不知道接收方发生了什么事情!
    • 发送方如何做?
      • 重传?可能重复
      • 不重传?可能死锁(或出错)
    • 需要引入新的机制
      • 序号
  • 处理重复:
    • 发送方每个分组中加入序号
    • 如果ACK/NAK出错,发送方重传当前分组
      • 如果给了一packet0,然后返回ACK,ACK出错,那么再来一个P0
    • 接收方丢弃(不发给上层)重复分组,返回一个ACK,然后发送方又可以发Packet1
  • 停等协议
    • 发送方发送一个分组,然后等待接收方的应答
notion image
notion image
rdt2.1:讨论
  • 发送方:
    • 在分组中加入序列号
    • 两个序列号(0,1)就足够了
      • 一次发送一个未经确认的分组
    • 必须检测ACK/NAK是否出错(需要EDC)
    • 状态数变成了两倍
      • 必须记住当前分组的序列号为0还是1
  • 接收方:
    • 必须检测接收到的分组是否是重复的
      • 状态会指示希望接收到的分组的序号为0还是1
    • 注意:接收方并不知道发送方是否正确收到了其ACK/NAK
      • 没有安排确认的确认
notion image
 

3.4.5 rdt2.2:无NAK的协议(优化处理,为一次发送多个准备)

notion image
notion image
  • 功能同rdt2.1,但只使用ACK(ack要编号)
  • 当前分组的反向确认用前一个分组的正向确认来代替
  • 接收方对最后正确接收的分组发ACK,以替代NAK
    • 接收方必须显式地包含被正确接收分组的序号
  • 当收到重复的ACK(如:再次收到ack0)时,发送方与收到NAK采取相同的动作:重传当前分组
  • 为后面的一次发送多个数据单位做一个准备
    • 一次能够发送多个
    • 每一个的应答都有:ACK, NACK: 麻烦
    • 使用对前一个数据单位的ACK,代替本数据单位的nak
    • 确认信息减少一半,协议处理简单
notion image
注意:接收方再次发送ack0,代表当前pkt1(NAK1=ACK0)出错。发送方重传当前分组packet1
notion image
ack0出错,发送方不知道收到了什么,再传一个pkt0,因为ptk有序号,所以接收方知道重复。重复扔掉,再给一个ack0(发送出错),发送方给ptk1,重新回到同步状态
解决掉了重复和ack出错问题
notion image
 

3.4.6 rdt3.0:具有比特差错和分组丢失的信道(超时重传机制)

新的假设:下层信道可能会丢失分组(数据或ACK)
  • 会死锁(发送方发送完ptk1,然后在等确认信号回传。接收方在等ptk1)
  • 机制还不够处理这种状况:
    • 检验和
    • 序列号
    • ACK
    • 重传
超时重传机制:发送方等待ACK一段合理的时间
链路层的timeout时间确定的传输层timeout时间是适应式的
  • 发送端超时重传:如果到时没有收到ACK->重传
  • 问题:如果分组(或ACK)只是被延迟了:
    • 重传将会导致数据重复,但利用序列号已经可以处理这个问题(丢弃即可)
    • 接收方必须指明被正确接收的序列号
  • 需要一个倒计时定时器
 
notion image
上图右边是分组丢失,超时重发
notion image
上图是确认丢失和超时重发,重复了ptk1,但是因为序列号可以检测。但两次pkt0发送,两次确认,效率低。
过早超时,会导致重发。即当前ACK1确认还没有收到,误认为没收到再次发送pkt1.
notion image
rdt3.0的性能
  • rdt3.0可以工作,但链路容量比较大的情况下,性能很差
    • 链路容量比较大,一次发一个PDU的不能够充分利用链路的传输能力
notion image
  • 瓶颈在于:网络协议限制了物理资源的利用!(一次发一个PDU)
notion image
RTT=2*Ttansmit=30ms
链路利用率100%,即时刻打时刻收,受限的为带宽
 

3.5 流水线协议

流水线协议允许发送方在未得到对方确认的情况下一次发送多个分组
  • 必须增加序号的范围:用多个bit表示分组的序号
  • 发送方/接收方要有缓冲区
    • 发送方缓冲:未得到确认,可能需要重传;
    • 接收方缓存:上层用户取用数据的速率<接收到的数据速率;接收到的数据可能乱序,排序交付(可靠)
  • 两种通用的流水线协议:回退N步(GBN)和选择重传(SR)

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

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

3.5.2 发送窗口的移动

发送窗口的移动->前沿移动
notion image
  • 发送窗口前沿移动的极限:不能够超过发送缓冲区
notion image
绿色:发送窗口的范围。红色:已发送但是没有被确认 发送缓冲区内的白色:没有发送 蓝色:已经收到确认的分组
真正的执行过程:发送缓冲区不动,分组移动。
采用相对滑动表示,分组不动,发送缓冲区移动
 
发送窗口的移动->后沿移动
notion image
notion image
  • 发送窗口后沿移动
    • 条件:收到老分组的确认
    • 结果:发送缓冲区罩住新的分组,来了分组可以发送
    • 移动的极限:不能够超过前沿
notion image

3.5.3 接收窗口

  • 接收窗口(receiving window)=接收缓冲区
    • 接收窗口用于控制哪些分组可以接收;
      • 只有收到的分组序号落入接收窗口内才允许接收
      • 若序号在接收窗口之外,则丢弃;
    • 接收窗口尺寸Wr=1,则只能顺序接收;
    • 接收窗口尺寸Wr>l,则可以乱序接收
      • 提交给上层的分组,要按序
    • 例子:Wr=l,在0的位置;只有0号分组可以接收:向前滑动一个,罩在1的位置,如果来了第2号分组,则丢弃;还要给出一个确认,最高分组序号的确认,这个时候顺序到来的最高分组是0号分组,所以ack0。来了4,也不收丢弃,再给出0号确认,
      • notion image
RW=1 Go-Back-N协议(GBN)
RW>1 Selective Repeat协议(SR)
 
滑动窗口(slide window)协议-接收窗口
接收窗口实际上等同于接收缓冲区,哪些分组可以被接收构成的空间
  • 接收窗口的滑动和发送确认
    • 滑动:
      • 低序号的分组到来,接收窗口移动;
      • 高序号分组乱序到,缓存但不交付(因为要实现rdt,不允许失序),不滑动
    • 发送确认:
      • 接收窗口尺寸=1发送连续收到的最大的分组确认(累计确认)
        • 比如给ack=2,那么0,1,2都以收到→累计确认
      • 接收窗口尺寸>1收到分组,发送那个分组的确认(非累计确认/独立确认)
        • 比如给ack=2,不能确认0,1是否收到→非累计确认
        • 高序号分组到来,可以缓存
    • 例子:接收窗口尺寸大于1,收到0,给确认ack=0;之后窗口顺序移动一个,收到1后,给确认ack=1.接收窗口再移动一个。这个时候来了3号分组。落在接收缓冲区可以接收。给3号确认ack=3。接收窗口不滑动(因为2号分组没有到来,滑动的条件,低号分组到来).4号分组到来,给确认ack=4,窗口不滑动。2号分组来,给确认ack=2,3,4解封装发给上层,同时窗口移动3个。(可靠传输含有保序特征)
notion image
notion image
 

3.5.4 正常情况下的2个窗口互动

  • 发送窗口
    • 新的分组落入发送缓冲区范围,发送->前沿滑动
    • 来了老的低序号分组的确认(后沿确认)->后沿向前滑动->新的分组可以落入发送缓冲区的范围
  • 接收窗口
    • 收到分组,落入到接收窗口范围内,接收
    • 是低序号,发送确认给对方
  • 发送端上面来了分组->发送窗口滑动->接收窗口滑动->发确认
  • 下图内容和上面文字一样,但是注意绿色箭头的推动关系。
notion image
 

3.5.5 异常情况下GBN的2窗口互动

异常情况:分组丢失,确认丢失/出错
  • 发送窗口
    • 新分组落入(未发送)发送缓冲区范围,发送->前沿滑动
    • (乱序到来的分组在GBN中被丢弃同时发送最高到达的分组确认,重复确认,发送窗口不移动并导致超时重发机制)超时重发机制让发送端将发送窗口中的所有分组发送出去
    • 来了老分组的重复确认->后沿不向前滑动->新的分组无法落入发送窗口的范围(此时如果发送缓冲区有新的分组可以发送)
  • 接收窗口
    • 收到乱序分组,没有落入到接收窗口范围内,抛弃
    • (重复)发送老分组的确认,累计确认
 

3.5.6 异常情况下SR的2窗口互动

  • 发送窗口
    • 新分组落入发送缓冲区范围,发送->前沿滑动
    • 超时重发机制让发送端将超时的分组(上一个例题的2号分组定时器到时后重发2号)重新发送出去
    • 来了乱序分组的确认->后沿不向前滑动->新的分组无法落入发送缓冲区的范围(此时如果发送缓冲区有新的分组可以发送)
  • 接收窗口
    • 收到乱序分组,落入到接收窗口范围内,接收
    • 发送该分组的确认,单独确认
 

3.5.7 GBN协议和SR协议的异同

  • 相同之处
    • 发送窗口>1
    • 一次能够可发送多个未经确认的分组
  • 不同之处
    • GBN: 接收窗口尺寸=1
      • 接收端:只能顺序接收
      • 发送端:从表现来看,一旦一个分组没有发成功,如:0,1,2,3,4;假如1未成功,234都发送出去了,要返回1再发送一遍1234;GB1
    • SR: 接收窗口尺寸>1
      • 接收端:可以乱序接收
      • 发送端:发送0,1,2,3,4,一旦1未成功,2,3,4已发送,无需重发,选择性发送1

3.5.8 流水线协议

  • Go-back-N:
    • 发送端最多在流水线中有N个未确认的分组
    • 接收端只是发送累计确认cumulative ack
      • 接收端如果发现gap,不确认新到来的分组
    • 发送端拥有对最老的未确认分组的定时器
      • 只需设置一个定时器(发送窗口下沿分组的定时器)
      • 当定时器到时,重传所有未确认分组
  • Selective Repeat:
    • 发送端最多在流水线中有N个未确认的分组
    • 接收方对每个到来的分组单独确认individual ack(非累计确认)
    • 发送方为每个未确认的分组保持一个定时器
      • 当超时定时器到时,只是重发到时的未确认分组

3.5.8.1 GBN协议

notion image
base=1,next=1,窗口大小=0,且从一号窗口开始发。
notion image
初始化后,收到分组sndpkt,且数据检验后,来了数据的序号和等待分组的序号一样hasseqnum(rcvpkt,expectedseqnum)。解封装:extract(rcvpkt,data)通过接口向上层发送数据,形成确认分组sndptk,发给对方,同时接收方窗口向前滑动++。
  • 只发送ACK:对顺序接收的最高序号的分组
    • 可能会产生重复的ACK
    • 只需记住expectedseqnum;接收窗口=1
      • 只一个变量就可表示接收窗口
  • 对乱序的分组:
    • 丢弃(不缓存)→在接收方不被缓存!
    • 对顺序接收的最高序号的分组进行确认-累计确认
notion image
notion image
假设发送缓存区的大小为4(未经确认的情况下可以连续发送4个分组)。发送pkt0,1,2,3这个时候wait因为发送缓冲区用完。当0号分组到达接收方,收(0变绿),解封装往上交。同时向前滑动。当1号分组到达接收方,收(1变绿),解封装往上交。同时向前滑动。假设pkt2丢失,收到pkt3,那么这个时候要给出1号窗口的确认.(接收方仍然罩在2上)接收方收到0号确认,变绿窗口滑动,发送4号pkt。接收方收到1号确认,变绿窗口滑动,发送5号pkt。收到4号pkt但是接收窗口仍然罩在2号,发送1号确认。收到5号pkt但是接收窗口仍然罩在2号,发送1号确认.
pkt2定时器到时间(最老未确认定时器),这个时候将发出所有已发送但是未确认的pkt2,3,4,5。2收到之后到3,3收到之后到4,4收到之后到5.

3.5.8.2 选择重传SR

  • 接收方对每个正确接收的分组,分别发送ACKn(非累积确认每)
  • 每发送一个分组,将启动对应分组的定时器。当相应的ACKn收到时,就把分组对应的定时器关闭
    • 接收窗口>1
      • 可以缓存乱序的分组
      • 最终将分组按顺序交付给上层
  • 发送方只对那些没有收到ACK的分组进行重发-选择性重发
    • 发送方为每个未确认的分组设定一个定时器
  • 发送窗口的最大值(发送缓冲区)限制发送未确认分组的个数
选择重传
  • 发送方
    • 从上层接收数据:
      • 如果下一个可用于该分组的序号可在发送窗口中,则发送
      • timeout(n):
        • 重新发送分组n,重新设定定时器
      • ACK(n) in [sendbase,sendbase+N]:
        • 将分组n标记为已接收
        • 如n为最小未确认的分组序号,则base移到下一个未确认序号
  • 接收方
    • 分组n [rcvbase, rcvbase+N-1]
      • 发送ACK(n)
      • 乱序:缓存
      • 有序:该分组及以前缓存的序号连续的分组交付给上层,然后将窗口移到下一个仍未被接收的分组
        • 先接收3,4窗口不移动。接收2发送确认后,将2,3,4一起解封装有序交付,同时窗口移动3个。
    • 分组n [rcvbase-N, rcvbase-1]
      • ACK(n)
    • 其它:
      • 忽略该分组
notion image
框框为发送缓冲区的范围。发送缓冲区、接收缓冲区(也代表发送窗口)的大小为4。低序号到来接收方窗口才会移动。发送pkt0,1,2,3.接收窗口收到0,移动窗口并发送ack0.接收窗口收到1,移动窗口并发送ack1.收到pkt3,在接收窗口内,缓存,发送ack3.发送窗口收到ack0,移动发,发送ptk4。收到ack1,移动发送pkt5。接收方收到pkt4,缓存,发送akc4.收到pkt5,缓存,发送ack5.ptk2的定时器到时(未收到ack2),这个时候只重发ptk2.接收方收到ptk2,那么ptk2,3,4,5顺序上交,并发送ack2.虽然这个时候ack3到达发送方,但是发送方不移动,缓存下ack3.当ack2到达时,ack2,3,4,5都收到,移动4个。
(注意:接收方缓存ptk,发送方也会缓存ack,都是收到最低reciv才会移动)
 

3.5.8.3 对比GBN和SR

notion image
  • 适用范围
    • 出错率低:比较适合GBN,出错非常罕见,没有必要用复杂的SR,为罕见的事件做日常的准备和复杂处理
    • 链路容量大(延迟大、带宽大):比较适合SR而不是GBN,一点出错代价太大(因为GBN需要全部重传)
 
窗口的最大尺寸
n来代表分组的序号,求GBN和SR的发送窗口序号最大值
  • GBN: 2^n-1
  • SR: 2^(n-1)
  • 例如:n=2;序列号?:0, 1, 2, 3
    • GBN = 3
    • SR = 2
  • SR的例子:
    • 接收方看不到二者的区别!
    • 将重复数据误认为新数据 (a)
 

3.5 面向连接的传输TCP

 

3.5.1 TCP特点

RFCs: 793, 1122, 1323, 2018, 2581
  • 点对点
    • 一个发送方,一个接收方
  • 可靠的、按顺序的字节流(数据报)
    • 应用进程将字节流提供给下方的TCP实体,对方的TCP实体将字节流交给应用进程
    • 不出错,不重复,不丢失,原原本本
    • 没有报文边界(应用进程交了两个报文,对方可能收到一个稍微大一点的报文/4个小一点的报文)
  • 管道化(流水线)
    • TCP拥塞控制和流量控制设置窗口大小
  • 发送和接收缓存
    • 发送缓冲区:发完之后要检错重发/超时重发等等
    • 接收缓冲区:发送方发送和读取的速率不一样(流量控制)
  • 全双工数据
    • 在同一连接中数据流双向流动
    • MSS:最大报文段大小
      • MTU:1500字节,每个报文段经过网络层之后还需要加上IP的头部,大小需要能装进一个MTU里面,所以报文很长需要根据MSS进行报文段的切分
    • 通过层间接口交给TCP实体报文,TCP实体。据MSS切分报文段,每个MSS前面加上TCP头部,形成TCP段。TCP段又叫做报文段
  • 面向连接
    • 在数据交换之前,通过握手(交换控制报文)初始化发送方、接收方的状态变量
  • 有流量控制、拥塞控制
    • 发送方不会淹没接收方

3.5.2 TCP 序号,确认号

notion image
  • 序号
    • 报文段首字节的在字节流的编号(偏移量)
      • notion image
        MSS承接在TCP的载荷部分。MSS第一个字节(也叫载荷部分/报文段的首字节)在字节流的偏移量用序号表示。如果第一个MSS的序号为X,第二个MSS的序号就是X+MSS…
  • 确认号
    • 期望从另一方收到的下一个字节的序号
    • 累积确认
    • 接收方发送555,那么554号及以前所有序号的报文段已经接收到,希望你传555。
  • Q: 接收方如何处理乱序的报文段-没有规定(可以接收也可以抛弃)
seq发送报文段的序号,ack期待接收报文段的序号。主机a发送42号报文,期待接收79号报文(78及以前序号的报文都已经接收),数据段为C。主机b发送79号报文,期待接收43号报文(42号报文即之前都有收到。)
notion image
 

3.5.3 TCP往返延时(RTT)和超时

Q: 怎样设置TCP超时?
  • 比RTT要长
    • 但RTT是变化的
  • 太短:太早超时
    • 不必要的重传
  • 太长:对报文段丢失反应太慢,消极
(有个RTT分布时间概率曲线,RTT很长,分布均匀采用自适应定时。RTT比较短,分布集中,期望和4方差)
Q: 怎样估计RTT?
  • SampleRTT:测量从报文段发出到收到确认的时间
    • 如果有重传,忽略此次测量
  • SampleRTT会变化,因此估计的RTT应该比较平滑
    • 对几个最近的测量值求平均,而不是仅用当前的SampleRTT
notion image
notion image
当前的采样值离平均的值的偏差的程度的平均值
 

3.5.4 TCP:可靠数据传输

GBN和SR的混合体
  • TCP在IP不可靠服务的基础上建立了rdt
    • 管道化的报文段
      • GBN or SR
    • 累积确认(像GBN)
      • ACK=555,那么接收方已经收到554及以前字节。期待发送方发送555号及以后的字节
    • 单个重传定时器(像GBN)
      • 只设置最老的那个段的定时器
      • 但是重传最早未确认的段(SR)
    • 是否可以接受乱序的,没有规范,可以缓存可以抛掉
  • 通过以下事件触发重传
    • 超时(只重发那个最早的未确认段:SR)
    • 重复的确认
      • 第一个确认正确,后面又收到同样的三个确认(冗余确认),即使超时定时器没有超时,但是三个冗余确认触发发送最早未确认的段。
      • 例子:收到了ACK50,之后又收到3个ACK50
      • 这种重传叫做快速重传

3.5.4.1 TCP发送方

notion image
(忽略流量控制,重复确认)
初始化:从初始化规定的序号开始发。接收到数据,创建一个段,前沿移动。超时,发送最老的那个发送未确认段。
如果收到ACK,那么需要滑动到ACK值的位置上y。(sendbase是后沿滑动,nextseqnum前沿)
这个时候新的发送窗口是y到nextseqnum,如果这里面还有发送未确认的段,那么需要重新启动定时器。如果这个窗口都是收到确认的段(base=next),关闭定时器。
 
TCP发送方事件:
  • 从应用层接收数据:
    • 用nextseq创建报文段
    • 序号nextseq为报文段首字节的字节流编号
    • 如果还没有运行,启动定时器
      • 定时器与最早未确认的报文段关联
      • 过期间隔:TimeOutInterval
  • 超时:
    • 重传后沿最老的报文段
    • 重新启动定时器
  • 收到确认:
    • 如果是对尚未确认的报文段确认
      • 更新已被确认的报文序号(移动后沿)
      • 如果当前还有未被确认的报文段,重新启动定时器
notion image
 
简化的TCP发送方
  • 注释:
    • SendBase-1: 最后一个累积确认的字节
  • 例:
    • SendBase-1 = 71;
    • y = 73,因此接收方期望73+;
    • y > SendBase,因此新的数据被确认
    •  
notion image

3.5.5 TCP重传

notion image
 
注意seq=92,8个字节。第1个字节为92,第2个字节为93…第8个字节为99.那么希望发送的ACK=100.可以总结出来:ACK=Seq+字节长度(偏移量或者MSS=8)
过早超时,重发最老未确认的段。看图上的时间轴,最老未确认的段是92.接收方给出的是顺序到来的序号+1的ACK(期待到来ACK+1)
注意这里虽然ACK=100的确认没有到发送方。但是ACK=120的确认已经到接收方(说明119即之前已经确认)。需要发送120号段。sendbase=120(指针头指向将要发送的段的开头)
notion image
 
产生TCP ACK的建议 [RFC 1122, RFC 2581]
notion image
接收方的事件
TCP接收方动作
所期望序号的报文段按序到达。所有在期望序号之前的数据都已经被确认
延迟的ACK。对下一个按序报文段的到达最多等待500ms。如果下一个报文段在这个时间间隔内没有到达,则发送一个ACK。
有期望序号的报文段到达。另一个按序报文段等待发送ACK
立即发送单个累积ACK,以确认两个按序报文段。
比期望序号大的报文段乱序到达。检测出数据流中的间隔
立即发送重复的ACK,指明下一个期待字节的序号为间隔段的期待
能部分或完全填充接收数据间隔的报文段到达。
若该报文段起始于间隔(gap)的低端,则立即发送ACK。
第一种情况:y0,y1到,发送ACK2,(隐忍不发ACK1)即两个段的确认一起发,减少对发送方的干扰(少发一个ACK1)y0到,y1在延时等待定时器内没到,赶紧发ACK1期待(表示y0到,期待y1到)。
第二种情况是:来了一个y0,已经有了ACK1(忍住不发),然后来了一个y1填补,那么立马发送ACK2(确认两个段)
notion image
第三种情况:比期望序号大的报文段乱序到达。立即发送重复的ACK,指明下一个期待字节的序号为间隔段的期待
第四种情况:如果乱序到达存在一个gap,如果来一个把gap补全,那么发送ACK=y2,如果部分补齐,那么发送ACK=y1
 

3.5.6 快速重传:三个冗余确认的重发

  • 超时周期往往太长:
    • 在重传丢失报文段之前的延时太长
  • 通过重复的ACK检测报文段丢失
    • 发送方通常连续发送大量报文段
    • 如果报文段丢失,通常会引起多个重复的ACK
    • 接收方发送最老未确认的ACK
      • notion image
  • 如果发送方收到同一数据的3个冗余ACK,重传最小序号的段
    • 快速重传:在定时器过时之前重发报文段
    • 它假设跟在被确认的数据后面的数据丢失了
      • 第一个ACK是正常的;
      • 收到第二个该段的ACK,表示接收方收到一个该段后的乱序段;
      • 收到第3,4个该段的ack,表示接收方收到该段之后的2个,3个乱序段,可能性非常大
notion image
notion image
notion image
如果y=100>sendbase=92,那么后沿sendbase=100需要移动到y。(第一次ACK有效)如果ACKy=sendbase=100,那么需要对ACK计数。当ACK=3,这里是冗余ACK=3,那么重传即快速重传。
 
 

3.5.7 TCP流量控制

  • 流量控制:接收方控制发送方,不让发送方发送的太多、太快以至于让接收方的缓冲区溢出
  • 接收方在其向发送方的TCP段头部的rwnd字段“通告”其空闲缓冲区buffer大小
    • RcvBuffer大小通过socket选项设置(典型默认大小为4096字节)
    • 很多操作系统自动调整RcvBuffer
  • 发送方限制未确认(“in-flight”)字节的个数<=接收方发送过来的rwnd值(空闲缓冲区大小)
  • 保证接收方不会被淹没
notion image
notion image
notion image
  • 这个用绝对值来表示吧。。。。
  • 最近收到的字节的指针-已读的指针,算出缓冲区已占据的大小。
  • 缓冲区未占据(空白区)的大小=缓冲区的大小-缓冲区已经被占据的大小
 
 

3.5.8 TCP连接管理

在正式交换数据之前,发送方和接收方握手建立通信关系
  • 同意建立连接(每一方都知道对方愿意建立连接)
  • 同意连接参数(连接建立序号、buffer大小,传输序号…准备好资源)
同意建立连接
Q:在网络中,2次握手建立连接总是可行吗?
A: 不行,存在下面
  • 变化的延迟(连接请求的段没有丢,但可能超时)
  • 由于“丢失”造成的重传(e.g. req_conn(x))
  • 报文乱序
  • 相互看不到对方
notion image
虚线之前连接维护数据传递。虚线之后连接拆掉了。
出现半连接和老数据当新数据接收的问题
notion image

3.5.9 TCP3次握手

notion image
  • 选择初始序号,x发送TCP SYN报文,同时置位标志位
  • 选择初始序号,y,发送SYNACK报文,确认SYN,同时置位标志位
  • 接收SYNACK(x)表明服务器是活跃的;发送SYNACK的ACK:该报文可能包含C-S的数据
  • 接收ACK(y)表明客户端是活跃的
我给你我的初始序号,(你给我确认,你给我你的初始序号→捎带),我给确认 三次握手
我知道你要y+1(从y+1开始传),你知道要从x+1之后开始传
x的确认,传递到的是ACK=x+1
 
3次握手解决:半连接和接收老数据的问题
notion image
  • 解决半连接问题
    • 确认超时,超时重发连接请求,服务器给出确认。虚线之前连接维护数据传递。虚线之后连接拆掉了。迟到的连接请求到达服务器,服务器同意建立连接,因为3次握手建立连接。(虚线之前只实现两次)。服务器发送连接确认,但是客户端知道这个连接是老连接,所以拒绝。
  • 解决接收老数据问题
    • 连接请求,连接确认。发送数据(传递数据和第三次握手合在一起),数据确认没来。定时器到时,再次重发数据。服务器发现已经建立了三次握手的连接并拆除,这个时候没有连接,数据扔掉。(滞留数据对服务器没有影响)
    • 但如果服务器和客户端又建立了连接,这个滞留的数据又达到服务器该怎么办呢?这不是也把老的数据当新数据处理了吗?
      • 初始序号起作用!!
        • 初始序号并不是从0开始,由上面的例子可以知道。一个是从x+1开始,一个是从y+1开始。但是这个滞留的数据的序号并不在新建立的连接的序号范围内!!!所以无法传递。
        • 当然也有可能这个滞留数据的序号就在这个新连接传递序号的范围内:
          • 解决方案:选一个一直在变的范围。→服务器和客户端选择的序号范围和时钟周期有关。时钟周期的第k位当作序号。
          • 你说周期又回来了,也可能造成问题,可能性很小,网络不能解决所有问题。
notion image
 

3.5.10 TCP:关闭连接

  • 客户端,服务器分别关闭它自己这一侧的连接
    • 发送FIN bit = 1的TCP段
    • 发送端的连接被关闭了,就不能再发数据。
    • 但是不影响发送方发应答,接收方的发数据
  • 服务器端:一旦接收到FIN,用ACK回应
    • 接到FIN段,ACK可以和它自己发出的FIN段一起发送
  • 可以处理同时的FIN交换
  • 不可靠的,因为请求和确认一直存在丢失的风险
notion image
服务器请求连接释放的时候,启动一个定时器,在这个定时器到时之前,没有数据再被接收到,那么这个连接就被真正关闭掉了。

3.6 拥塞控制原理

  • 拥塞
    • 非正式的定义:“太多的数据需要网络传输,超过了网络的处理能力”
    • 与流量控制不同
    • 拥塞的表现
      • 分组丢失(路由器缓冲区溢出)
      • 分组经历比较长的延迟(在路由器的队列中排队)
  • 拥塞的“代价”
    • 为了达到一个有效输出,网络需要做更多的工作(重传)
    • 没有必要的重传,链路中包括了多个分组的拷贝"
      • 是那些没有丢失,经历的时间比较长(拥塞状态)但是超时的分组
      • 降低了的“goodput”
  • 拥塞控制方法
    • 网络不拥塞的情况下尽可能大的提高速率
      最初注入速率:吞吐速率=1:1,后面注入1,吞吐(输出)达不到1
    • 端到端的拥塞控制:
      • 不从网络中得到明确的反馈 从端系统根
      • 据观察到的时延丢失现象推断出拥塞
      • TCP所采用的方法
    • 网络辅助拥塞控制:
      • 路由器利用数据流通过拥塞的路由器,向发送接收主机提供直接反馈
      • 可以指示拥塞级别或明确设置发送速率
      • 指示发送方按照一定速率发送
      • TCP ECN, ATM, DECbit protocols
      • 直接反馈虽然信息精准,但是路由器负担重,网络代价大

3.7 TCP拥塞控制

复杂性不放在网络核心(路由),放在网络边缘。
TCP 拥塞控制:机制
  • 端到端的拥塞控制机制
    • 路由器不向主机有关拥塞的反馈信息
    • 路由器的负担较轻
    • 符合网络核心简单的 TCP/IP架构原则
  • 端系统根据自身得到的信息,判断是否发生拥塞,从而采取动作
  • 拥塞控制的几个问题
    • 如何检测拥塞
      • 轻微拥塞
      • 拥塞
    • 控制策略
      • 在拥塞发送时如何动作,降低速率
        • 轻微拥塞,如何降低
        • 拥塞时,如何降低
      • 在拥塞缓解时如何动作,增加速率
 

3.7.2 TCP 拥塞控制:拥塞感知

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

3.7.3 TCP 拥塞控制:速率控制方法

如何控制发送端发送的速率
  • 维持一个拥塞窗口的值:CongWin
  • 发送端限制已发送但是未确认的数据量(的上限): LastByteSent-LastByteAcked ≤ CongWin
  • 从而粗略地控制发送方向的注入的速率
    • notion image
  • CongWin是动态的,是感知到的网络拥塞程度的函数
    • 超时或者3个重复ackCongWin↓
      • 超时CongWin降为1MSS,进入SS阶段(慢启动阶段)然后再倍增到CongWin/2(每个RTT),从而进入CA阶段
      • 3个重复ack:CongWin降为CongWin/2,CA阶段
    • 否则(正常收到ack,没有发送以上情况):CongWin跳跃欲试↑
      • SS阶段:加倍增加(每个RTT)
        • 慢启动阶段,指数增加
      • CA阶段:线性增加(每个RTT)
        • 拥塞避免阶段,线性增加
        • 临界点:CongWin/2
 

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

联合控制的方法:
  • 发送端控制发送但是未确认的量同时也不能够超过接收窗口满足流量控制要求(接收窗口→流量控制)
    • SendWin=min(CongWin, RecvWin)
    • ≤CongWin:满足拥塞控制
    • ≤RecvWin:接收缓冲区的空闲尺寸,满足流量控制
  • 同时满足拥塞控制和流量控制要求
 
 

3.7.5 TCP 拥塞控制:策略概述

拥塞控制策略:
  • 慢启动
  • AIMD:线性增,乘性减少
  • 超时事件后的保守策略
 

3.7.5.1 TCP 慢启动

  • 连接刚建立,CongWin = 1 MSS
  • MSS:报文段的最大长度(以太网1500B-20B(TCP头部)-20B(IP头部))
    • 如:MSS = 1460bytes & RTT = 200 msec
    • 初始速率 = 58.4kbps
      • notion image
  • 可用带宽可能 >> MSS/RTT
    • 应该尽快加速,到达希望的速率
  • 当连接开始时,指数性增加发送速率直到发生丢失的事件
    • 启动初值很低
    • 但是增长速度很快
TCP 慢启动(续)
  • 当连接开始时,指数性增加(每个RTT)发送速率直到发生丢失事件
    • 最初CongWin=1MSS,即发送一个报文段
    • 每一个RTT,CongWin加倍
    • 每收到一个ACK,CongWin加1(这两句话等价,一个RTT即过去回来)
    • 慢启动阶段:只要不超时或3个重复ack,一个RTT,CongWin加倍
  • 总结:初始速率很慢,但是加速却是指数性的
    • 指数增加,SS时间很短,长期来看可以忽略
    •  
notion image
Q:什么时候应该将指数性增长变成线性? A:在超时之前,当Congwin变成上次发生超时的窗口的一半
  • 实现:
    • 变量:Threshold
    • 出现丢失,Threshold设置成CongWin的1/2
    • eg:16个发生拥塞,那么将拥塞值的一半设置为警戒值。
  • 1,2,4,8,然后线性增加。12发生拥塞,将CongWin的一半6当为警戒值(这里拥塞默认为超时,拥塞窗口大小降到1)。然后1,2,4,6,8,9,10
  • 如果到达12是发生了3个重复ACKs(轻微拥塞),那么窗口值降到一半就变成6,7,8,9这么增加,Threshold=6,CongWin=Threshold+3=9
 
notion image
 

3.7.5.2 TCP 拥塞控制:AIMD

notion image
  • 乘性减:
    • 丢失事件后将CongWin降为1,
      • 将CongWin/2作为阈值,进入慢启动阶段(倍增到CongWin/2)
  • 加性增:
    • 当CongWin>阈值时,一个RTT如没有发生丢失事件,将CongWin加1MSS
 
TCP 拥塞控制:AIMD
  • 当收到3个重复的ACKs
    • CongWin减半
    • 窗口(缓冲区大小)之后线性增长
  • 超时事件发生时:
    • CongWin被设置成1MSS,进入SS阶段
    • 之后窗口指数增长
    • 增长到一个阈值(上次发生拥塞的窗口的一半)时,再线性增加
 

3.7.6 总结:TCP拥塞控制

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

3.7.7 TCP 吞吐量

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

3.7.8 TCP 公平性

  • 公平性目标:如果K个TCP会话分享一个链路,带宽为R的瓶颈,每一个会话的有效带宽为R/K
    • notion image
为什么TCP是公平的?
  • 2个竞争的TCP会话:(RTTAA’=RTTBB‘)
    • 加性增加,斜率为1,吞吐量增加
    • 乘性减,吞吐量比例减少
  • 无失:将拥塞窗口减半
  • 丢失:将拥塞窗口减半,拥塞窗口的值丢失;线性增加拥塞窗口的值
  • 相对公平:
    • notion image
      从主机角度看,BB’占9/10带宽,AA’占1/10.如果分别建立1个连接,但BB’往返延时少,那么B抢占大带宽也更大。
notion image
notion image
最后收敛到X=Y
 
公平性和UDP
  • 多媒体应用通常不是用TCP
    • 应用发送的数据速率希望不受拥塞控制的节制
  • 使用UDP:
    • 音视频应用要求数据的速率是恒定的,忽略数据的丢失
  • 研究领域:TCP 友好性
Explicit Congestion Notification (ECN)
  • 网络辅助拥塞控制:
    • TOS字段中2个bit被网络路由器标记,用于指示是否发生拥塞
    • 拥塞指示被传送到接收主机
    • 在接收方-到发送方的ACK中,接收方(在IP数据报中看到了拥塞指示)设置ECE bit,指示发送方发生了拥塞
 
 

3.10 总结

  • 传输层提供的服务
    • 应用进程间的逻辑通信
      • vs 网络层提供的是主机到主机的通信服务
    • 互联网上传输层协议:UDP
      • 特性:
        • Rdt1.0 rdt2.0,2.1, 2.2 Rdt 3.0
  • 多路复用和解复用
    • 端口:传输层的SAP
    • 无连接的多路复用和解复用
    • 面向连接的多路复用和解复用
  • 实例1:无连接层协议UDP
    • 多路复用解复用
    • UDP报文格式
    • 检错机制:校验和
  • 可靠数据传输原理
    • 问题描述
    • 停止等待协议:Rdtl.0 rdt2.0,2.1 ,2.2 Rdt 3.0
    • 流水线协议
      • GBN
      • SR
  • 实例2:面向连接的传输层协议-TCP
    • 概述:TCP特性
    • 报文段格式
      • 序号,超时机制及时间
    • TCP可靠传输机制
      • 确认,快速重传
      • 流量控制
    • 连接管理
      • 三次握手
      • 对称连接释放
  • 拥塞控制原理
    • 网络辅助的拥塞控制
    • 端到端的拥塞控制
  • TCP的拥塞控制
    • AIMD
    • 慢启动
    • 超时之后的保守策略
 
第三章 展望
  • 下二章:
    • 离开网络“边缘”(应用层和传输层)
    • 深入到网络的“核心”
    • 2个关于网络层的章
      • 数据平面
      • 控制平面
第2章:应用层第4章:网络层
Loading...
目录
0%
🐟🐟
🐟🐟
在坚冰还盖着北海的时候,我看到了怒放的梅花
最新发布
第1章:计算机网络概述
2025-6-30
2-6-1 uC/OSII 在STM32上的移植
2025-6-23
1-6 定时器与PWM
2025-6-21
一些工具
2025-6-21
第5章:链路层和局域网
2025-6-19
第4章:网络层
2025-6-19
公告
🎉 欢迎来到鱼鱼的博客~ 🎉
--- 很高兴认识你~ ---
👏一起成为理想中的自己吧!👏
目录
0%