知识点回顾(自顶向下)
Posted 之墨_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识点回顾(自顶向下)相关的知识,希望对你有一定的参考价值。
第三章知识点回顾
- 1.传输层概述
- 2.多路复用与解复用
- 3.无连接传输UDP
- 4.可靠数据传输
- 5.选择重传(Selective Repeat)
- 6.面向连接的传输:TCP
- 7.TCP流量控制
- 8.连接管理
- 9.拥塞控制
- 例题
1.传输层概述
- Our goals:
- 理解传输层服务原理:
- 多路复用与多路分解
- 可靠数据传输
- 流量控制
- 拥塞控制
- 理解传输层服务原理:
- 学习因特网的传输层协议:
- UDP: 无连接传输
- TCP: 面向连接的传输
- TCP拥塞控制
- 传输层把 应用层报文 (message) 转换成传输层分组, 即报文段(segment) .
- 主要协议有 UDP 和 TCP 协议.
- 网络层提供主机之间的逻辑通信;
- 传输层提供进程之间的逻辑通信 .
- 传输层依赖并增强网络层的服务 .
1.1传输服务
- 在应用程序看来:
- 源进程向本地套接字写入报文或数据,目的进程在本地套接字即可收到报文或数据
- 源进程和目的进程仿佛直接连接在一起
- 传输层提供了进程间的逻辑通信
- 在传输层看来:
- 发送方传输层将报文交给本地网络层接口,接收方传输层从本地网络层接口即可收到报文
- 网络层提供了终端间的逻辑通信
1.2传输层与网络层的关系
- 网络层:提供主机之间的逻辑通信
- 传输层:提供进程之间的逻辑通信
- 传输层依赖并增强网络层服务
- 网络层提供尽力而为的服务:
- 网络层尽最大努力在主机间交付分组,但不提供任何承诺
- 具体来说,不保证交付,不保证按序交付,不保证数据完整,不保证延迟,不保证带宽,……
- 传输层不能提供的服务:
- 延迟保证
- 带宽保证
- 传输层可以提供的服务:
- 保证可靠、按序的交付:TCP
- 不保证可靠、按序的交付:UDP
2.多路复用与解复用
- 传输层基本服务:
- 将主机间交付扩展到进程间交付
- (发送端)多路复用:
- 传输层从多个套接字收集数据,交给网络层发送
- (接收端)解复用:
- 传输层将收到的数据交付到正确的套接字 How?—(通过 套接字 标识)
2.1如何进行多路复用和解复用
- 为将邮件交付给收信人:
- 每个收信人应有一个信箱,写有收信人地址和姓名(唯一标识)
- 信封上有收信人地址和名字
- 为将报文段交付给套接字:
- 主机中每个套接字应分配一个唯一的标识
- 报文段中包含接收套接字的标识
- 多路复用:
- 发送方传输层将源/目的套接字标识置于报文段中,交给网络层
- 解复用:
- 接收方传输层根据报文段中的目的套接字标识,将报文段交付到正确的套接字
2.2套接字与端口号
- 端口号是套接字标识的一部分
- 每个套接字在本地关联一个端口号
- 端口号:
- 一个16比特的数
- 0~1023由公共域协议使用,称众所周知的端口号
- 报文段中有两个字段携带端口号
- 源端口号:与发送进程关联的本地端口号
- 目的端口号:与接收进程关联的本地端口号
2.2.1如何分配UDP套接字的端口号
-
自动分配:
- 例如,new Datagramsocket(),不指定端口号
- 通常由操作系统从1024~65535中分配
- 客户端通常使用这种方法
-
使用指定端口号创建套接字:
- 例如,new Datagramsocket(53)
- 实现公共域协议的服务器应分配众所周知的端口号
- 服务器通常采用这种方法
-
UDP套接字标识为<IP地址,端口号>二元组
2.2.2UDP解复用
- 接收方传输层收到一个UDP报文后:
- 检查报文中的目的端口号,将UDP报文交付到具有该端口号的套接字
- <目的IP地址,目的端口号> 相同的UDP报文被交付给同一个套接字,与 <源IP地址,源端口号> 无关
- 报文中的 <源IP地址,源端口号> 被接收进程用来发送响应报文
2.2.3创建TCP套接字
- 服务器在port=x创建一个欢迎套接字:
- welcomeSocket = new ServerSocket(x)
- 客户A创建一个与欢迎套接字通信的客户套接字(假设自动分配端口号y):
- clientSocket = new Socket(“hostname”, x)
- 服务器在收到客户A的连接请求后创建一个连接套接字:
- connectionSocket = welcomeSocket.accept()
- 该连接套接字只与客户A的套接字通信,即只接收具有以下四元组的报文段:
- 源IP地址 = 客户A的IP地址
- 源端口号 = y
- 目的IP地址 = 服务器的IP地址
- 目的端口号= x
- 不同的客户进程与服务器上不同的连接套接字对应
2.2.4TCP解复用
- 服务器主机可能有多个连接套接字
- 每个连接套接字与一个进程相联系,并由 <源IP地址,目的IP地址,源端口号,目的端口号> 四元组进行标识
- 服务器使用该四元组将报文段交付到正确的连接套接字
小结
-
UDP套接字
- 使用<IP地址,端口号>二元组标识套接字
- 服务器使用一个套接字服务所有客户
-
TCP套接字
- 使用<源IP地址,目的IP地址,源端口号,目的端口号> 四元组标识连接套接字
- 服务器使用多个连接套接字,每个连接套接字服务一个客户
-
socket 标识与端口号: 端口号是 socket 标识的一部分.
- UDP 的 socket 标识是一个二元组: <IP 地址, 端口号 >
- 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
-
网络层提供的服务(best-effort service):
- 尽最大努力将数据包交付到目的主机
- 不保证投递的可靠性和顺序
- 不保证带宽及延迟要求
-
UDP提供的服务:
- 进程到进程之间的报文交付
- 报文完整性检查(可选):检测并丢弃出错的报文
-
UDP需要实现的功能:
- 多路复用与解复用
- 报文检错
3.1UDP报文结构
- UDP报文:
- 报头:携带协议处理需要的信息
- 载荷(payload):携带上层数据
- 用于多路复用/解复用的字段:
- 源端口号,目的端口号
- 用于检测报文错误的字段:
- 报文总长度
- 检查和(checksum)
3.2 UDP检查和(checksum)
- 作用: 对传输的报文进行检错
- 发送方:
- 将报文看成是由16比特整数组成的序列
- 对这些整数序列计算检查和
- 将检查和放到UDP报文的checksum字段
- 接收方:
- 对收到的报文进行相同的计算
- 与报文中的checksum字段进行比较:
- 不相等:报文有错误
- 相等:认为没有错误
- UDP检查和计算
-
计算UDP检查和包括伪头、UDP头和数据 三个部分。
-
检查和的使用是可选的 ,若不计算检查和,该字段填入0。
-
计算检查和时,checksum字段填0
-
接收方对UDP报文(包括检查和)及伪头求和,若结果为0xFFFF,认为没有错误
-
3.3为什么需要UDP
- 应用可以尽可能快地发送报文:
- 无建立连接的延迟
- 不限制发送速率(不进行拥塞控制和流量控制)
- 报头开销小
- 协议处理简单
- UDP适合的应用:
- 容忍丢包但对延迟敏感的应用:如流媒体
- 以单次请求/响应为主的应用:如DNS
- 若应用要求基于UDP进行可靠传输:
- 由应用层实现可靠性
4.可靠数据传输
- 什么是可靠传输: 数据不会有比特损坏或丢失, 并按照发送的顺序被接收. 如何在不可靠的网络层上实现可靠的传输协议?
- 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可靠传输协议设计过程
- 不可靠信道有哪些出错类型:比特错误,丢包
- 如何发现错误:接收方通过检错码发现出错包,利用定时器发现丢失包
- 采取什么恢复措施:重传出错或丢失的包
- 恢复措施引入的问题:ACK出错、ACK丢失或超时设置过短,导致接收端出现冗余分组
- 如何解决冗余分组的问题:给分组加上序号,序号多长
- 将以上措施汇总,画出各种情形下的时间线图(正常,分组出错,ACK出错,分组丢失,ACK丢失,过早超时)
- 归纳发送方、接收方的事件类型及采取的动作,画出FSM
4.2 流水线可靠数据传输协议
- rdt3.0是一种停-等(stop-and-wait)协议
- rdt3.0是一个正确的协议,但性能不佳!
- 流水线:提高链路利用率
- 流水线协议: 允许发送方有多个已发送、未确认的分组
- 分组的序号范围应扩大(停等协议只使用1比特序号)
- 发送端和接收端可能需要缓存多个分组(停等协议中,发送端缓存一个分组,接收端不缓存)
- 两种基本的流水线协议: go-Back-N, selective repeat
4.3Go-Back-N
- 收发规则:
- Sender:
- 最多允许N个已发送、未确认的分组
- 对于最早的已发送、未确认的分组使用一个定时器
- 若定时器超时, 从最早已发送、未确认的分组开始,顺序发送其后的分组
- Receiver:
- 每收到一个分组,都要发送一个带序号的ACK
- 对于未按顺序到来的分组,丢弃,重发最近一次的ACK
- 使用 累积确认: 若ACK包含序号q,表明“序号至q的分组均正确收到”
- Sender:
- 概念:
- 已发送未确认序号 + 未发送可用序号 = 发送窗口(包含N个序号)
- Ack分组携带所确认分组的序号
- 使用累积确认: 若ACK包含序号q,表明“序号至q的分组均正确收到”
- 若发送方收到ACK q,则更新基序号为 q+1,整体滑动发送窗口
- 发送方只对基序号分组使用一个定时器
- 超时:发送方重传发送窗口中从基序号开始的所有分组
4.4 GBN的发送方
- 收到上层的发送请求:
- 若发送窗口满:拒绝请求
- 若发送窗口不满:
- 构造分组并发送(从下一个可用序号开始设置)
- 若原来发送窗口为空:对基序号启动一个定时器
- 收到ACK q:
- 更新基序号为q+1
- 若发送窗口变为空:终止定时器
- 若发送窗口不空:对基序号启动一个定时器
- 收到出错的ACK:
- 不做处理,为什么?
- 若ack p出错,可由后续收到的ack q(q>p)进行累积确认
- 若ack p出错,且后续未收到ack,则超时后重传 pkt p
- 不做处理,为什么?
- 定时器超时:
- 启动定时器,从已发送未确认的分组开始,发送位于当前发送窗口内的所有分组
GBN小结
- 接收端:
- 按顺序接收分组,不缓存失序的分组
- 按照累积确认的要求发送ACK
- 发送端:
- 仅当发送窗口不满时,才能发送新的分组
- 收到确认后,更新发送窗口
- 当发送窗口发生变化(空<->非空,基序号更新)时,需要重新设置定时器
- 超时后,重发发送窗口中的全部分组
- 特点:
- 接收端简单,发送端复杂,出错后需要较多的重传
5.选择重传(Selective Repeat)
-
要点:
- 发送方仅重传它认为出错(未收到ACK)的分组,以避免不必要的重传
-
为此:
- 接收端需缓存失序的分组
- 接收端需对每个正确收到的分组单独确认(选择确认) (注意:选择重传不使用累积确认)
- 发送的每个分组需要一个定时器,以便被单独重发
5.1SR的发送窗口和接收窗口
- 发送窗口:
- 包含“已发送未确认”和“未发送可用”的序号
- 可能有“已发送已确认”的序号交织其中
- 基序号是“已发送未确认”或“未发送可用”的序号
- 收到基序号的ACK时,滑动发送窗口
- 接收窗口:
- 包含“期待但未收到”和“允许接收”的序号
- 可能有“已确认已缓存”的序号交织其中
- 基序号为“期待但未收到”或“允许接收”的序号
- 收到基序号分组时,按顺序交付分组,滑动接收窗口
5.2选择重传的工作过程
- 发送方:
- 从上层接收数据:
- 若发送窗口未满,发送分组,启动定时器
- 定时器 n 超时:
- 重传分组n, 重启定时器
- 收到发送窗口内的ACK(n) :
- 标记分组n为已确认
- 若n=基序号,滑动发送窗口,使基序号=最小未确认的序号或下一个序号
- 其余情形:
- 忽略
- 从上层接收数据:
- 接收方:
- 收到接收窗口内的分组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] ,但其中有分组没有被正确接收,发送端超时后重发该分组。如果接收端不响应这个分组,那发送方的发送窗口将不能更新,发送停滞。
- 收到接收窗口内的分组n:
5.3 选择重传:窗口大小和序号空间的关系
- 选择重传:通常发送窗口大小 = 接收窗口大小
- 考虑以下情形:发送方发送了一个满窗口([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不能大于序号空间的一半
小结
- 接收端:
- 落在接收窗口中的分组都要接收,每个分组单独确认
- 尽管允许乱序接收,但仍须按顺序交付数据
- 发送端:
- 发送窗口不满时可以发送新的分组
- 每个已发送的分组都需要一个定时器
- 若定时器n超时,只重发序号为n的分组
- 特点:
- 出错后重传代价小,发送端使用较多定时器,接收端需要较大缓存,实现复杂
- 梳理流水线机制的设计
- 一次允许发送多个包会带来什么新的问题:
- 序号长度k,窗口大小N和k有什么关系,发现分组出错或丢失怎么处理
- GBN:一旦发现出错后,接收方不再接收新的包,双方从出错的包开始重新发送和接收
- SR:发现出错后,接收方可以继续接收落在接收窗口内的包,过后仅发送/接收出错的包
- 画出GBN和SR的时间线图,据此画出FSM
- 一次允许发送多个包会带来什么新的问题:
6.面向连接的传输:TCP
6.1序号和确认序号
- 序号:
- 报文段中第一个数据字节的序号
- 确认序号:
- 使用累积确认,指出期望从对方接收的下一个字节的序号
- (确认号就是接收方期待的下一个字节序号)
- 确认号对于 TCP 超时设置的作用:
- 估计 RTT: 测量从发出某个报文段到收到其确认之间经过的时间, 作为 SampleRTT.
- Q: 接收方如何处理失序的报文段?
- A: TCP规范未涉及,留给实现者考虑
- 举例
6.2TCP超时设置
- 如何设置TCP超时值?
- 超时值太小:
- 产生不必要的重传
- 超时值太大:
- 丢失恢复的时间 太长
- 应大于RTT:
- RTT是变化的
- 超时值太小:
- Q: 如何估计RTT?
- SampleRTT:
- 测量从发出某个报文段到收到其确认报文段之间经过的时间
- SampleRTT是变化的,更有意义的是平均RTT
- SampleRTT:
6.3 估算平均RTT
-
EstimatedRTT = (1- α)*EstimatedRTT + α*SampleRTT
\\textEstimatedRTT = (1- α)*EstimatedRTT + α*SampleRTT
EstimatedRTT = (1- α)*EstimatedRTT + α*SampleRTT
- 指数加权移动平均
- 典型值: α = 0.125
- 瞬时RTT和平均RTT有很大的偏差
- 应当在EstimtedRTT 加上一个“安全距离”,作为超时值
- 安全距离的大小与RTT的波动幅度有关
6.4 设置超时值
- SampleRTT 与 EstimatedRTT的偏差估计:
- 设置超时值:
6.5 TCP可靠数据传输
- TCP 在不可靠的IP服务上建立可靠的数据传输
- IP层信道:IP包可能出错、丢失、重排序
- TCP采用的数据传输机制:
- 发送端采用流水式发送报文段
- 接收端采用累积确认进行响应
- 发送端采用重传来恢复丢失的报文段
6.6 一个高度简化的TCP协议
- 仅考虑可靠传输机制,且数据仅在一个方向上传输
- 接收方:
- 仅在正确、按序收到报文段后,更新确认序号;其余情况,重复前一次的确认序号(与GBN类似,使用累积确认)
- 缓存失序的报文段(与SR类似)
- 发送方:
- 流水式发送报文段
- 仅对最早未确认的报文段使用一个重传定时器(与GBN类似)
- 仅在超时后重发最早未确认的报文段(与SR类似,接收端缓存了失序的报文段)
- 接收方:
6.7TCP发送方处理的事件
- 收到应用数据:
- 创建并发送TCP报文段
- 若当前没有定时器在运行(没有已发送、未确认的报文段),启动定时器
- 超时:
- 重传包含最小序号的、未确认的报文段
- 重启定时器
- 收到ACK:
- 如果确认序号大于基序号:
- 推进发送窗口(更新基序号)
- 如果还有未确认的报文段,启动时器,否则终止定时器
- 如果确认序号大于基序号:
6.8快速重传
- 仅靠超时重发丢失的报文段,恢复太慢!
- 利用重复ACK检测报文段丢失:
- 发送方通常连续发送许多报文段
- 若报文段丢失,会有许多重复ACK发生
- 多数情况下IP按序交付分组,重复ACK极有可能因丢包产生
- 协议规定:当发送方收到对同一序号的3次重复确认时,立即重发包含该序号的报文段
- 快速重传: 在定时器到期前重发丢失的报文段
小结
- 可靠传输的设计:
- 流水式发送报文段
- 采用累积确认
- 只对最早未确认的报文段使用一个重传定时器
- 超时后只重传包含最小序号的、未确认的报文段
- 以上措施可大量减少因ACK丢失、定时器过早超时引起的重传
- 超时值的确定:
- 基于RTT估计超时值+ 定时器补偿策略
- 测量RTT:
- 不对重传的报文段测量RTT
- 不连续使用推迟确认
- 快速重传:
- 收到3次重复确认,重发报文段
6.9TCP与GBN/SR对比
-
Go-Back-N
- 接收方:
- 使用累积确认
- 不缓存失序的分组
- 对失序分组发送重复ACK
- 发送方:
- 超时后重传从基序号开始的所有分组
- 接收方:
-
TCP
- 接收方:
- 使用累积确认
- 缓存失序的报文段
- 对失序报文段发送重复ACK
- 发送方:
- 超时后仅重传最早未确认的报文段
- 增加了快速重传
- 接收方:
-
SR
- 接收方:
- 缓存失序的分组
- 每个分组使用一个定时器
- 单独确认每个正确收到的分组
- 发送方:
- 超时后仅重传未被确认的分组
- 接收方:
-
修改的TCP [RFC2018]
- 接收方:
- 缓存失序的报文段
- 只对最早未确认的报文段使用一个定时器
- SACK选项头中给出收到的非连续数据块的上下边界
- 发送方:
- 仅重传接收方缺失的数据
- 增加了快速重传
- 接收方:
6.10TCP结合了GBN和SR的优点
- TCP的可靠传输机制可以看成是 GBN和SR的混合体:
- 定时器的使用:与GBN类似,只对最早未确认的报文段使用一个定时器
- 超时重传:与SR类似,只重传缺失的数据
- TCP在减小定时器开销和重传开销方面要优于GBN 和 SR!
7.TCP流量控制
- 问题:
- 进入接收缓存的数据不一定被立即取走、取完
- 若应用消费数据的速度较慢,接收缓存可能溢出
- 流量控制:
- 发送端TCP调节发送速率,不使接收端缓存溢出
- 为什么GBN或SR不考虑流量控制
- GBN和SR均假设:
- 正确、按序到达的分组被立即交付给上层
- 其占用的缓冲区被立即释放
- 从而,GBN和SR不会出现接收端缓存溢出的问题
- GBN和SR均假设:
- 为什么UDP没有流量控制:
- UDP不保证交付:
- 接收端UDP将收到的报文载荷放入接收缓存
- 应用进程每次从接收缓存中读取一个完整的报文载荷
- 当应用进程消费数据不够快时,接收缓存溢出,报文数据丢失,并不违反UDP的服务承诺
- UDP不保证交付:
7.1接收窗口
- 接收缓存中的可用空间称为接收窗口(RcvWindow)
- 接收方将RcvWindow放在报头中,向发送方通告接收缓存的可用空间
- 发送方限制未确认的字节数不超过接收窗口的大小,即:
7.2零窗口通告和零窗口探测
- 特别是,发送端收到RcvWindow = 0的报文段(零窗口通告)时,必须停止发送,然后:
- 发送端启动一个定时器
- 定时器超时后,发送端发送一个零窗口探测报文段(序号为上一个段中最后一个字节的序号)
- 接收端在响应的报文段中通告当前的接收窗口
- 若发送端仍收到零窗口通告,重新启动定时器
说明:零窗口探测的唯一作用是触发接收端发送响应
7.3糊涂窗口综合症(silly window syndrome)
- 当数据发送很快、而消费很慢时,零窗口探测的简单实现带来以下问题:
- 接收方不断发送微小窗口通告
- 发送方不断发送很小的数据分组
- 大量带宽被浪费
- 接收端避免糊涂窗口综合症的策略:
- 通告零窗口之后,仅当窗口大小显著增加之后才发送更新的窗口通告
- 什么是显著增加:窗口大小达到缓存空间的一半或者一个MSS,取两者的较小值
- TCP执行该策略的做法:
- 当窗口大小不满足以上策略时,推迟发送确认(但最多推迟500ms,且至少每隔一个报文段使用正常方式进行确认),寄希望于推迟间隔内有更多数据被消费
- 仅当窗口大小满足以上策略时,再通告新的窗口大小
- 发送方避免糊涂窗口综合症的策略:
- 发送方应积聚足够多的数据再发送,以防止发送太短的报文段
- 问题:发送方应等待多长时间?
- 如等待时间不够,报文段会太短
- 如等待时间过久,应用程序的时延会太长
- 更重要的是,TCP不知道应用程序会不
- 在最近的将来生成更多的数据
小结
- TCP接收端:
- 使用显式的窗口通告告知发送方可用的缓存空间大小
- 在接收窗口较小时推迟发送确认(条件允许的话)
- 在零窗口通告后,仅当接收窗口显著增加时通告新的窗口大小
- TCP发送端:
- 使用Nagle算法确定发送时机
- 使用接收窗口限制发送的数据量(已发
- 未确认的字节数不超过接收窗口的大小)
8.连接管理
- 建立连接要确定两件事:
- 双方都同意建立连接(知晓另一方想建立连接)
- 初始化连接参数(序号,MSS等)
8.1TCP三次握手
- Step 1: 客户TCP发送SYN 报文段
(SYN=1, ACK=0)- Seq = 客户的起始序号
- Ack:无有效内容
- 不包含数据
- Step 2: 服务器TCP发送SYNACK报文段(SYN=ACK=1)
- Seq = 服务器的起始序号
- Ack = 客户起始序号+1
- 不包含数据(服务器端分配缓存和变量)
- Step 3: 客户发送ACK报文段(SYN=0,ACK=1)
- Seq =客户起始序号+1
- Ack = 服务器起始序号+1
- 可以包含数据(客户端分配缓存和变量)
8.2起始序号
-
为什么起始序号不从1开始?
- 若每个新建连接都从序号1开始,那么在不同时间、同一对套接字之间建立的连接,它们的握手报文段都一样,且旧连接上的报文段可能会干扰新连接上的传输(报文段序号有重叠)
-
可以随机选取起始序号吗?
- 新、旧连接上报文段序号重叠的可能性将大为减小,但不能完全避免
-
必须避免新、旧连接上的序号产生重叠
-
基于时钟的起始序号选取算法:
- 每个主机使用一个时钟,以二进制计数器的形式工作,每隔ΔT时间,计数器加1
- 新建一个连接时,以计数器值的最低32位作为起始序号
- 该方法确保连接的起始序号随时间单调增长
-
取较小的ΔT,确保起始序号的增长速度超过TCP连接上序号的增长速度
-
使用较长的序号(32位),确保序号回绕的时间远大于分组在网络中的最长寿命
8.3关闭连接
- 关闭连接: 四次挥手
9.拥塞控制
- 交通拥堵(类比的例子):
- 起因:大量汽车短时间内进入路网,超出路网的承载能力
- 表现:道路通行能力下降,车速变慢,甚至完全停滞
- 措施:减少车辆进入(交通管制)
- 网络拥塞:
- 起因:大量分组短时间内进入网络,超出 网络的处理能力
- 表现:网络吞吐量下降,分组延迟增大
- 措施:减少分组进入网络(拥塞控制)
- 流量控制与拥塞控制:
- 流量控制:限制发送速度,使不超过接收端的处理能力
- 拥塞控制:限制发送速度,使不超过网络的处理能力
9.1流量控制与拥塞控制区别
- 流量控制是端到端的控制
- 例如A通过网络给B发数据,A发送的太快导致B没法接收(B缓冲窗口过小或者处理过慢),这时候的控制就是流量控制
- 原理是通过滑动窗口的大小改变来实现。
- 拥塞控制是A与B之间的网络发生堵塞导致传输过慢或者丢包,来不及传输。
- 防止过多的数据注入到网络中,这样可以使网络中的路由器或链路不至于过载。
- 拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络性能有关的所有因素。
9.2 网络拥塞的代价
-
延迟增大
- 拥塞发生在路由器中:
- 对于路由器的某条输出链路而言,当进入该链路的数据速率接近或超出链路带宽时,就会发生拥塞
- 代价一:分组延迟增大
- 即使不考虑丢包(假设有无限大的缓存),当链路接近满载时,排队延迟急剧增大
- 拥塞发生在路由器中:
-
吞吐量下降
- 场景一:
- 路由器输出缓存溢出,发送端TCP重传被丢弃的包
- 场景二:
- 发送端定时器过早超时,产生了不必要的重传
- 场景一:
9.3拥塞控制方法
-
端到端拥塞控制:
- 网络不向端系统提供显式反馈
- 端系统通过观察丢包和延迟来推断拥塞的发生,进而降低发送速率
- TCP采用此类方法
-
网络辅助的拥塞控制:
- 发生拥塞的路由器向相关的发送端/接收端提供直接反馈,指示拥塞 程度或直接给出发送速率
- 发送端相应降低发送速率
- TCP ECN, ATM, DECbit协议采用此方法
9.4TCP拥塞控制
- TCP使用端到端拥塞控制机制:
- 发送方根据自己感知的网络拥塞程度,限制其发送速率
- 发送方如何感知拥塞?
- 利用丢包事件感知拥塞
- 丢包或分组延迟过大,对于发送端来说都是丢包了
- 丢包事件包括:
- 超时
- 3次重复的ACK
- 利用丢包事件感知拥塞
- 发送方调节拥塞窗口的策略
- 加性增、乘性减
- 慢启动
- 发送方使用拥塞窗口CongWin限制已发送未确认的数据量:
- CongWin随所感知的网络拥塞程度而变化
9.5加性增、乘性减(AIMD)
- 乘性减:每检测到一个丢包事件,CongWin减半(迅速减小),但不能小于一个MSS
- 加性增: 若没有丢包,每经过一个RTT,CongWin增大一个MSS(缓慢增大),直到检测到丢包
9.6慢启动
- 连接刚建立时
- CongWin = 1 MSS
- 按照加性增来增大CongWin:
- 每隔一个RTT才能增大一个MSS,速度太慢!
- 希望迅速增大CongWin至可用的发送速度
- 基本思想:
- 在新建连接上指数增大CongWin,直至检测到丢包(此时终止慢启动过程)
9.6.1慢启动的实施
- 慢启动的策略:
- 每经过一个RTT,CongWin加倍
- 具体实施方法:
- 每收到一个ACK段,CongWin增加一个MSS
- 特点:
- 以一个很低的速率开始,按指数增大发送速率
9.7区分不同的丢包事件
- 丢包事件:
- 收到3个冗余ACK:说明网络仍有一定的交付能力
- 超时:说明网络交付能力很差
- 目前的TCP实现区分不同的丢包事件
- 收到3个冗余ACK:
- CongWin降为一半
- 采用AIMD调节
- 超时:
- CongWin = 1MSS
- 使用慢启动增大CongWin,至 超时发生时CongWin的一半
- 使用AIMD调节
9.7.1 实现
- 发送方维护一个变量Threshold
- 发生丢包时,Threshold设置为当前CongWin的一半:
- 若收到3次重复的ACK:令 CongWin = Threshold+3*MSS,执行AIMD(已有3个报文段到达接收端,不再占用网络资源,扩大CongWin以允许再发送3个报文段)
- 若发生的是超时:CongWin = 1*MSS,执行慢启动
- 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,并不违反拥塞窗口的限流要求。
状态图
小结
- 当CongWin < Threshold时,发送方处于慢启动阶段, 拥塞窗口指数增长
- 当CongWin >= Threshold时,发送方处于拥塞避免阶段, 拥塞窗口线性增长
- 当收到3个冗余ACK 时, Threshold = CongWin/2, CongWin = Threshold + 3MSS(快速恢复)
- 当超时发生时, Threshold = CongWin/2 , CongWin =1 MSS
9.8 TCP吞吐量
-
一个长期存活的TCP连接的平均吞吐量是多少?(忽略慢启动阶段)
-
令W=发生丢包时的CongWin,此时
throughput = W/RTT -
发生丢包后调整 CongWin=W/2,此时throughput=W/2RTT
-
假设在TCP连接的生命期内,RTT 和 W几乎不变,则:Average throughout=0.75 W/RTT
-
-
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=2∗10−10
-
针对高速网络需要新的TCP拥塞控制算法
-
9.9TCP的公平性
- 公平性目标:
- 如果K条TCP连接共享某条带宽为 R R R的瓶颈链路,每条连接具有平均速度 R / K R/K R/K。
- TCP公平性更复杂的情形
- 若相互竞争的TCP连接具有不同的参数(RTT、MSS等),不能保证公平性;
- 若应用(如web)可以建立多条并行TCP连接,不能保证带宽在应用之间公平分配;比如,一条速率为R的链路上有9条连接:
- 若新应用建立一条TCP连接,获得速率 R/10
- 若新应用建立11条TCP,可以获得速率 R/2 !
9.10 关于TCP和UDP的思考
-
能否说TCP服务优于UDP服务?
- 不同应用对传输层服务有不同的需求,适合的就是好的,所以不存在哪个服务绝对的好、或绝对的不好。
-
多媒体应用希望的传输层服务是:带宽有保证,延迟有保证,顺序有保证,但能忍受一些丢包。TCP或UDP能够满足多媒体应用的需求吗?
- 根据多媒体应用希望的传输层服务,显然 TCP或UDP都不能完全满足。
小结
- 传输服务原理:
- 多路复用、解复用
- 可靠数据传输
- 流量控制
- 拥塞控制
- Internet中的传输服务:
- UDP
- TCP
例题
-
是非判
以上是关于知识点回顾(自顶向下)的主要内容,如果未能解决你的问题,请参考以下文章