第三章-运输层 复习大纲
- 传输层服务背后的原理
- 多路复用,多路分解
- 可靠数据传输
- 流量控制
- 拥塞控制
- 因特网中的实例和实现
- UDP
- TCP
这一章东西是真的多,难度也比前两章高
3.1 传输层服务
- 传输层:为两个不同的主机上运行的应用程序之间提供 逻辑通信
- 传输层协议运行在端系统
- 发送方:将应用程序报文分成 数据段 传递给网络层
- 接收方:将数据段重新组装为 报文 传递到应用层
- 不止一个传输层协议可以用于应用程序
- 因特网:TCP & UDP
- 对比传输层和网络层
- 传输层:两个 进程 之间的逻辑通信——可靠,增强的网络层服务
- 网络层:两个 主机 之间的逻辑通信
- Internet 传输层协议
- TCP:可靠按需递交
- 拥塞控制、流量控制、建立连接
- 但是不提供延迟保证、带宽保证
- UDP:不可靠的无需传递
- ”尽力传递“,IP的直接拓展
- TCP:可靠按需递交
- 传输层协议运行在端系统
3.2 多路复用和多路分解
- 多路复用:在发送主机处多路复用
- 在多个套接字收集数据,用 首部封装数据 ,然后将报文段传递到网络层
- 多路分解:在接收主机多路分解
- 将接收到的数据段传递到正确的套接字
-
多路分解的工作方式
- 主机收到IP数据报
- 每个数据报有 源IP地址、目的IP地址
- 每个数据包搬运一个数据段
- 每个数据段有 源和目的端口号(对于特定应用程序具有周知端口号)
- 主机用IP地址和端口号指明数据段属于哪个合适的套接字
- 主机收到IP数据报
-
无连接多路分解
-
用端口号创建套接字
DatagramSocket ServerSocket1 = new DatagramSocket(38460);
-
UDP套接字由两个因素指定:目的IP地址+目的端口号
-
主机收到UDP数据段后
- 检查数据段中的目的端口号
- 用端口号指示UDP数据段属于哪个套接字
-
具有相同目的IP地址和目的端口号的IP数据报(无论源IP地址和源端口号是否一致),指向相同的套接字
-
-
面向连接的多路分解
- TCP套接字由4部分指定:源IP地址、源端口号、目的IP地址、目的端口号,接受主机使用这4个值将数据段定位到合适的套接字
- 服务器主机可同时支持多个TCP套接字
P4,P5,P6可以用一个多线程服务器P4替代(此时一个P4服务器有3个端口)
3.3 UDP:无连接传输
-
UDP:”无修饰“”不加渲染的“”尽最大努力的“互联网传输层协议。
-
无连接——UDP的接收者和发送者之间不需要握手、每个UDP数据段的处理独立于其他数据段
-
缺点——数据段可能会:丢失、传递失序的报文到应用程序
-
为什么会有UDP:
- 简单、减少延迟(不需要建立连接)
- 很小的数据段首部
- 没有拥塞控制(因为UDP能够以尽可能快的速度传递)
-
与 IP 的数据报服务相比,只增加了端口的功能和差错检查的功能
-
UDP的头部开销小,只有8个字节
-
源端口(Source Port):2字节,发送方端口号。
-
目的端口(Destination Port):2字节,接收方端口号。
-
长度(Length):2字节,UDP报文的总长度(包括首部和数据部分)。
-
校验和(Checksum):2字节,用于错误检测。
-
-
-
UDP面向报文——对应用程序交下来的报文保持完整性,保留了应用层数据的边界。
-
发送方:UDP对应用程序交下来的数据报添加首部后,直接向下交付给IP层。一旦UDP将数据报发出,不保证其到达、不保证顺序、不重传。
-
接收方:UDP从IP层接收到数据报后,去除首部,然后将数据报原封不动地交给上层应用进程。
-
-
优缺点总结:
- 优点
- 低开销:由于UDP首部只有8个字节,协议开销很小,适合需要快速传输和低延迟的应用。
- 简单高效:没有连接建立和拆除的过程,减少了传输延迟,适合实时应用。
- 保留报文边界:UDP保留应用层报文的边界,方便应用程序处理
- 缺点
- 无可靠性:UDP不保证数据报的到达、不保证顺序、不提供重传机制。需要应用层自行处理可靠性。
- 无流量控制:UDP不提供流量控制,可能导致网络拥塞或丢包。
- 无错误恢复:UDP只提供简单的校验和用于错误检测,但不提供错误恢复机制。
- 适用场景
- 实时视频和音频流:例如视频会议、VoIP(网络语音)。
- 实时在线游戏:需要低延迟的数据传输。
- 简单的查询服务:如DNS查询。
- 广播和组播:需要将数据发送给多个接收方的场景。
-
UDP 校验和计算
-
并非100%可靠
-
伪首部包含以下字段,总共12个字节:
- 源IP地址(4字节)
- 目的IP地址(4字节)
- 保留字段(1字节):值为0
- 协议字段(1字节):值为17,表示UDP协议
- UDP长度字段(2字节):表示UDP数据报的总长度,包括首部和数据部分(与首部中的长度一致)
-
处理方法
- 发送发:将首部中的校验和暂时置为0(要参与运算的),将数据段看成16位的整数序列,计算校验和放入UDP的校验和域
- 接收方:计算接收到数据段的校验和,检查与校验和域中的校验和是否一致(但就算一致也可能出错了)
-
计算方法:
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 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 // 校验和
-
例题:
源IP地址: 192.168.1.1(0xC0A80101)
目的IP地址: 192.168.1.2(0xC0A80102)
源端口: 12345(0x3039)
目的端口: 80(0x0050)
数据: “Hello”(对应的ASCII码:0x48656c6c6f)
UDP长度= 8(头部)+ 5(数据)=13 (0x000D)
- 构建伪首部:
源IP地址 | 目的IP地址 | 0 | 17 | UDP长度 C0A8 | 0101 | C0A8 | 0102 | 0000 | 0011 | 000D
- 构建UDP头部和数据
源端口 | 目的端口 | UDP长度 | 校验和 3039 | 0050 | 000D | 0000 数据部分: 4865 | 6c6c | 6f00 // 不足补0
- 全部进行16位累加
C0A8 + 0101 + C0A8 + 0102 + 0000 + 0011 + 000D + 3039 + 0050 + 000D + 0000 + 4865 + 6c6c + 6f00 = 5A31A 回卷: A31A + 0005 = A31F 取反: ~0xA31F = 0x5CE0
- 所以完整的UDP头部是:
3039 | 0050 | 000D | 5CE0
-
3.4 可靠数据传输
-
可靠传输协议(rdt,Reliable Transport Protocol)
-
Rdt1.0:完全可靠信道上的可靠数据传输
-
没有bit错误、没有分组丢失
-
发送方发送数据到下层信道,接收方从下层信道接收数据
注:虚线表示初始状态
- rdt_send():由应用层调用,将数据交付给接收端的上层应用
- udt_send():由 rdt 调用,将数据报通过不可信信道传输至接收端
- rdt_rcv():当数据报到达接收端后被调用,用来接收packet
- deliver_data():由 rdt 调用,将数据交付给上一层
发送方FSM:
- 状态:等待数据
(等待上层数据到达)
- 事件:从上层接收到数据 → \rarr → 数据打包 → \rarr → 发送数据包 → \rarr → 转移到状态:等待数据
接收方FSM:
- 状态:等待数据
(等待从信道接收数据包)
- 事件:接收到数据包 → \rarr → 数据开包 → \rarr → 提交数据给上层 → \rarr → 转移到状态:等待数据
-
-
Rdt2.0:具有bit错误的信道
-
下层信道可能让传输分组中的bit受损——校验和将检测到bit错误
-
如何从错误中恢复?(Acknowledgements & Negative Acknowledgements)
- 确认(ACKs):接收方 明确告诉 发送方——分组接收正确
- 否认(NAKs):接收方 明确告诉 发送方——分组接收错误
-
相较于 rdt1.0 的新机制:
- 差错检测(校验和):数据和头部的ACK/NAK都会计算校验和
- 接收方的反馈 rcvr → \rarr → sender(ACKs & NAKs)
-
FSM(有限状态机,Finite State Machine)规范:
-
有错 & 无错 的情况:
- 没有错误就正常处理再返回ACK(左图)
- 有错误就直接返回NAK,然后sender再重新传,直到receiver返回ACK sender才进入等待态(右图)
-
问题:只考虑了数据包传输时出现的bit错误,没考虑到ACK/NAK出现的问题!(ACK出现bit位翻转变成了NAK)
- 解决方法:重发。
- 但是重发可能重复,所以发送发给每个分组加一个序号,在ACK/NAK混淆时发送方重发当前分组,接收方丢弃重复的分组(就不向上传递了)—— 停等协议(发送方发送一个报文,然后等待接受方的响应)需要多少序号?——0,1 循环用
-
-
-
Rdt2.1:
-
假设和行为:
- 信道不丢包,但数据包可能损坏——发送方接收到损坏的ACK和NAK都会重新发送当前数据包,重启计时器
- 使用序列号区分数据包
- ACK和NAK都带有校验和,用于检测二者是否损坏
- case1:sender发送了一个0号数据包,receiver接收了,返回ACK但是翻转成了NAK,sender收到一个损坏的NAK——
此时,sender重发0号数据包,receiver如果接收错误返回NAK要求重发(即使这里发的是重新发的0号包而不是期望的1号包);如果是接收正确,receiver会丢弃这个新的0号数据包,返回ACK,让sender发送1号包(下一个数据)。如果这个ACK又变成NAK则不断循环直到成功。
(下图右下角的处理)
- case2:sender发送了一个0号数据包,receiver拒绝了,返回NAK但是翻转成了ACK,sender收到一个损坏的ACK——
此时,sender重发0号数据包,如果接收错误还是要求重发;如果接受正确,receiver会返回ACK。
(下图左下角的处理)
由于ACK/NAK带校验位,所以不会出现NAK翻转成ACK后sender错误地发送下一个数据包的情况
-
缺点:
- 有NAK更复杂;并且即使引入了 NAK,接收方仍然需要处理重复的数据包,并发送冗余的 ACK,增加了处理负担。
- 信道可能丢失数据包(receiver并不知道它的上一个ACK/NAK是否被sender正确收到)
- 每次只能传1个包,效率低;重传效率低
-
-
Rdt2.2:不要NAK的协议
- ACK → \rarr → ACK 0
- NAK → \rarr → ACK 1
-
Rdt3.0:考虑到包不仅可能会受损,还可能会丢失——引入超时重传
-
发送方FSM如下(接收方FSM同2.2的):
-
rdt3.0的停等操作:
性能分析:1Gbps链路,15ms传播时延,8000bit数据包,30ms RTT
T t r a n s m i t = L R = 8000 b i t 1 0 9 b / s = 8 μ s T_{transmit}=\frac{L}{R}=\frac{8000bit}{10^{9}b/s}=8\mu s Ttransmit=RL=109b/s8000bit=8μs
U s e n d e r = L / R R T T + L / R = 8 30 ∗ 1 0 3 + 8 = 0.00027 U_{sender}=\frac{L/R}{RTT+L/R}=\frac{8}{30*10^{3}+8}=0.00027 Usender=RTT+L/RL/R=30∗103+88=0.00027 // Utilization - 发送方忙于发送的时间占比(利用率)
1KB/30ms 即 33KB/s(1Gbps链路)——这是一个网络协议严重影响链路资源利用的一个例子
-
流水线技术:发送方允许发送多个 “在路上的”, 还没有确认的报文。(右图)——> 增加利用率
-
序号数目的范围必须增加
-
在发送方/接收方必须有缓冲区
-
两个通用形式:GBN & 选择重传
-
-
GBN(Go-Back-N,回退 N 重传协议)
-
发送方:
- 在分组头中规定一个k位的序号
- 滑动窗口(允许连续未确认的报文)
-
接收方:
- 为正确接收的最高序号的分组发送ACK(即上图一直发ACK1);由于没有接收缓冲区,所有只记住期待接收的序号
- 若接收到失序分组,丢弃,重发最高序号分组的ACK
-
问题:3,4,5都是正常的但还是会重复发
-
-
SR(Selective Repeat,选择重传协议)
-
窗格底部留在没有接收的分组处,在那之后收到的正常收(缓存);未被确认的报文超时后sender会重新发送,receiver收到后移动窗格到下一个没有接收的分组处,继续正常收。
-
发送方:
- 从上层收到数据后,如果下一个可用序号在发送方窗口内,则将数据打包发送,启动定时器
- 超时(n),重发分组n,重启定时器
- 收到ACK(n)在 [sendbase,sendbase+N-1]中
- 标记分组n被接受
- 如果n是最小的未确认分组,则提高窗口到下一个未被确认的序号
-
接收方收到分组n时:
-
若n在窗口内 [rcvbase,rcvbase+N-1] :发送ACK(n)
-
若接收后窗口是失序分组(不全),则继续缓冲
-
若接收后窗口是有序分组,则交付上层(和已经缓冲的有序分组一起,提高窗口到下一个没有接受的分组)
假如目前窗口是 [ , 3 , 4 , , 6],那么收到2之后,交付2,3,4,窗口变为[ , 6 , , , ]
-
-
若n在上一个窗口内 [rcvbase-N,rcvbase-1] :发送ACK(n)
-
-
窗口大小 ≤ 序号空间大小 2 窗口大小 \leq \frac{序号空间大小}{2} 窗口大小≤2序号空间大小
-
两难选择:
上图(b)情况中,由于没有收到ACK,sender的窗口不会挪动
-
-
Rdt 总结:
RDT 1.0: 无差错的信道
在这种情况下,假设信道是完美的,即没有数据包丢失、数据包损坏或数据包延迟。此时,数据传输协议不需要任何特殊机制,只需将数据从发送方传输到接收方即可。这种情况下的协议非常简单,因为信道本身是可靠的。
RDT 2.0: 信道可能发生数据损坏
在这种情况下,信道可能会导致数据损坏。为了检测和恢复这种情况,RDT 2.0引入了以下机制:
- 校验和:发送方在数据包中加入校验和,接收方接收数据包后计算校验和并与数据包中的校验和比较,以检测是否存在数据损坏。
- 确认(ACK)和否定确认(NAK):接收方在接收到数据包后发送ACK(确认)或NAK(否定确认)给发送方,以通知发送方数据是否正确接收。若接收到NAK,发送方重新发送数据包。
RDT 2.1: 处理NAK的改进
RDT 2.1在RDT 2.0的基础上,改进了对NAK的处理,使用ACK来确认接收,并使用序列号来区分不同的包。若接收到的数据包损坏,接收方将不发送ACK,发送方在超时后重新发送数据包。
RDT 2.2: 只使用ACK
RDT 2.2进一步改进,完全去除了NAK的使用,只通过ACK来确认数据包。接收方通过重复上一个正确接收的包的ACK来告知发送方当前数据包有误,发送方再重新发送该数据包。
RDT 3.0: 信道可能丢失数据包
在这种情况下,信道不仅可能损坏数据包,还可能丢失数据包。为了解决这个问题,RDT 3.0引入了超时重传机制:
- 超时重传:发送方在发送数据包后启动定时器,若在定时器到期前未收到接收方的ACK,则认为数据包丢失或损坏,重新发送数据包。
- 滑动窗口协议:用于提高传输效率,允许发送方在未接收到ACK的情况下连续发送多个数据包。
优化:GBN & SR
3.5 TCP:面向连接传输
集 GBN 和 SR 的优点
- 概述:
- 点到点
- 可靠按序的字节流,没有信息边界
- 流水线:TCP拥塞 & 流量控制设置窗口大小
- 收发缓冲区
- 全双工数据:同一个连接上的双向数据流(MSS:最大报文段长)
- 面向连接:数据交换前先握手(交换控制信息),初始化收发方的状态
- 流量控制:发送方不会淹没接收方
-
报文段的结构:
- TCP报文段首部格式
- 端口(2字节):运输层和应用层的服务接口。运输层的复用和分用都要通过端口实现。
- 序号(4字节):本报文段所发送的数据的第一个字节的序号(TCP中传送的数据流中每个字节都会被编上一个序号)。
- 确认号(4字节):期望收到对方的下一个报文段的数据的第一个字节的序号。
- 数据偏移(0.5字节,4位):以32位(4字节)为单位来表示数据偏移(表示 TCP报文段的数据起始处距离TCP报文段的起始处有多远,也就是TCP首部的长度)。
- 保留字段(0.75字节,6位):为以后使用,目前置为0.
- 紧急URG(1位):URG=1,表示优先级高(Urgent)
- 确认ACK(1位):ACK=1,字段才有效
- 复位RST(1位):RST=1,TCP连接时出现严重错误,需要释放连接再重连(Reset)
- 同步SYN(1位):SYN=1,表示这是一个连接请求or连接接收报文(Synchronize)
- 终止FIN(1位):FIN=1,表示此报文段的发送端的数据已发送完毕,并要求释放运输链接(Finish)
- 窗口(2字节):用来让对方设置发送窗口的依据,单位为字节
- 校验和(2字节):计算时和UDP一样要加上12字节的伪首部(源IP + 目的IP + 0x0000 + 0x0011 + 2字节的TCP长度)
- 紧急指针(0~4字节):指出本报文段中紧急数据的长度(紧急数据再报文段数据的最前面),单位为字节
- 填充字段(和紧急指针加起来一共4字节):凑数的(TCP长度要是4的倍数字节那么长)
-
TCP的序号和确认
- 初始序号 ISN:随机选而不固定从0开始,防止网络中的攻击,增强TCP连接的安全性
- 确认:期望从另一边收到的下一个字节的序号
- 接收方如何处理失序的数据段?——TCP规范未明确规定,由编程人员处理。(PPT上就这么写的)
-
TCP往返时延的估计和超时
-
设置的TCP超时值要比RTT长——但是RTT是变化的。
- 太短:不成熟的超时,不必要的重传
- 太长:对数据段丢失响应慢,效率低
-
样本RTT:测量从报文段发送到收到确认的时间(忽略重传)。由于它是变化的,因此需要一个样本RTT均值(EstimatedRTT),对收到的样本RTT要进行如下均值处理:
-
迭代公式: E s t i m a t e d R T T = ( 1 − α ) ∗ E s t i m a t e d R T T + α ∗ S a m p l e R T T EstimatedRTT=(1-\alpha)*EstimatedRTT+\alpha*SampleRTT EstimatedRTT=(1−α)∗EstimatedRTT+α∗SampleRTT
-
该均值计算称为“指数加权移动平均”,典型的 α = 0.125 \alpha=0.125 α=0.125
-
-
设置超时:EstimatedRTT + “安全余量”(类似波动率,EstimatedRTT越大,安全余量更大)
-
DevRTT 计算公式: D e v R T T = ( 1 − β ) ∗ D e v R T T + β ∗ ∣ S a m p l e R T T − E s t i m a t e d R T T ∣ DevRTT=(1-\beta)*DevRTT+\beta * |SampleRTT-EstimatedRTT| DevRTT=(1−β)∗DevRTT+β∗∣SampleRTT−EstimatedRTT∣
典型的 β = 0.25 \beta=0.25 β=0.25
-
设置超时时间间隔: T i m e o u t I n t e r v a l = E s t i m a t e d R T T + 4 ∗ D e v R T T TimeoutInterval=EstimatedRTT+4*DevRTT TimeoutInterval=EstimatedRTT+4∗DevRTT
-
初始时令 T i m e o u t I n t e r v a l = 1 s TimeoutInterval=1s TimeoutInterval=1s
-
获得第一个 S a m p l e R T T SampleRTT SampleRTT 后,令 E s t i m a t e d R T T = S a m p l e R T T EstimatedRTT=SampleRTT EstimatedRTT=SampleRTT, D e v R T T = S a m p l e R T T 2 DevRTT=\frac{SampleRTT}{2} DevRTT=2SampleRTT
T i m e o u t I n t e r v a l = E s t i m a t e d R T T + m a x ( G , 4 ∗ D e v R T T ) TimeoutInterval=EstimatedRTT+max(G,4*DevRTT) TimeoutInterval=EstimatedRTT+max(G,4∗DevRTT) ,其中 G 是用户设置的时间粒度,使得安全余量不小于某个常数
-
-
-
可靠数据传输
- TCP 在 IP 的不可靠服务上创建 rdt 服务
- 流水线技术处理报文段
- 累积确认(这会导致效率问题,解决方法 SACK 不考)
- TCP 使用单个重发定时器
- 触发重发:
- 超时重发
- 重复确认
-
发送方事件:
-
从应用程序接收数据后,用初始序号(报文中第一个数据字节在字节流中的位置编号,是随机生成的)创造一个报文。
-
如果未启动定时器则启动定时器(因为定时器是 最早没有被确认的报文 发送时启动的),设置超时间隔 TimeoutInterval
-
超时:
- 重发导致超时的报文
- 重新开始定时器
-
收到确认
- 如果 ACK 落在窗口内,则确认对应的报文并滑动窗口
- 若还有未确认的报文,重启定时器
-
-
快速重传:
超时重传的问题:超时周期太长,增加网络时延
TCP采用的是累计确认机制,即当接收端收到比期望序号大的报文段时,便会重复发送最近一次确认的报文段的确认信号,我们称之为冗余ACK(duplicate ACK)。
-
发送方可以在超时之前通过重复的 ACK 检测丢失的报文段
- 发送方常常一个接一个地发送很多报文段
- 若报文段丢失,那么发送方可能会收到很多重复的 ACK
-
如果发送方收到 3次重复确认( 即 4 个对同一报文段地确认,因为第一个不算重复),则发送方认为该报文段之后的数据已经丢失。
-
启动快速重传:在定时器超时之前重发丢失的报文段。
-
以下内容参考:TCP的快速重传机制_快重传包括第一个-CSDN博客
假设发送顺序为N,N+1,N+2,前一个发了N-1
- 如果N没丢失,那么接收方的到达顺序有 A 3 3 = 6 A_{3}^{3}=6 A33=6 种可能:
- N,N+1,N+2 sender收到 1 个ACK(N)
- N,N+2,N+1 sender收到 1 个ACK(N)
- N+1,N,N+2 sender收到 2 个ACK(N)
- N+1,N+2,N sender收到 3 个ACK(N)
- N+2,N,N+1 sender收到 2 个ACK(N)
- N+2,N+1,N sender收到 3 个ACK(N)
(也就是说 上面六种情况中,N 在第几个位置,那么 sender就会收到几个ACK(N) )
- 如果N丢失了,那么就只有 A 2 2 = 2 A_{2}^{2}=2 A22=2 种情况了:
- N+1,N+2
- N+2,N+1
(两种情况都相当于 N 在第三个位置,sender 收到 3 个ACK(N) )
根据此规律,如果序列有N,N+1,N+2,N+3,那么:
- 如果N丢失—— sender必定收到 4 个 ACK(N) ,即 3 个重复
- 如果N没丢失—— sender 收到 4 个 ACK的概率是 $\frac{A_{3}{3}}{A_{4}{4}}=25% $
- 图1:某报文段的超时重传定时器溢出前重传丢失报文段
- 图2:图1对应地接收端缓存队列的窗口移动示意
-
-
产生TCP ACK 的建议
接收方的事件 TCP接收方行为 1. 期望序号的报文段按序到达,所有在期望序号以前的报文段都被确认 延迟ACK,等到500ms看是否有下一个报文段,如果没有,发送ACK 2. 期望序号的报文段按序到达,另一个按序报文段等待发送 立即发送单个累积ACK,确认两个有序的报文段 3. 收到一个失序的报文段,高于期望的序号,检测到缝隙 立即发送重复ACK,指出期望的序号 4. 到达的报文段部分地 or 全部地填充接收数据间隔 立即发送ACK,证实缝隙低端的报文段已经收到 -
TCP 流量控制
TCP 连接的接收方有一个接收缓冲区,APP 可能从这个缓冲区中读出数据很慢
-
速度匹配服务:发送速率和接收 APP 的提取速率匹配
-
流量控制:发送发不能发送太多太快,让接收缓冲区溢出( v 发 ≈ v 收 & & n 发 ≤ n 剩余容量 v_{发}\approx v_{收} \space \&\& \space n_{发}\leq n_{剩余容量} v发≈v收 && n发≤n剩余容量 )
-
工作原理:
-
注:接收窗口的单位是字节
-
TCP连接管理
-
建立连接:三次握手:(TCP在交换数据报文段之前在收发方之间建立连接,首先初始化TCP的序号、缓冲区流控信息)
- 客户发送TCP SYN报文段到服务器
- 指定初始的序号
- 没有数据
- 服务器接收 SYN,回复 SYN & ACK 报文段
- 服务器分配缓冲区
- 指定服务器的初始序号
- 客户接收 SYN/ACK ,回复 ACK 报文段,可能包含数据
双方都要对信道做至少一次的确认!
第二步相当于 receiver 给 sender 一个关于信道 OK 的确认;
第三步相当于 sender 给 receiver 一个关于信道 OK 的确认。
“我说的话要有回应!”
三次握手的主要目的是:确认双方选择的序号!
-
关闭连接:四次挥手:客户关闭套接字
-
客户发送 TCP FIN 控制报文段到服务器
-
服务器接收到 FIN ,回复 ACK,进入半关闭连接状态。此状态下还能传数据,直到传完了再回复 FIN
-
服务器发送 FIN 到客户,启动 timer;
客户接收 FIN ,回复 ACK。在此同时,客户端进入”time wait“状态(如下图标注处),等待结束时释放连接资源
-
服务器接收 ACK,服务器端连接关闭。客户端在上一步中等够 2msl没有收到服务器端报文也会关闭。
为什么客户端要等 2*msl?
因为如果服务器端没有收到第三步中 客户端发送的 ACK 报文,服务器就不能正常关闭连接。
服务器端的 timer 超时之后会重新发送第三步的 FIN 报文,让客户端重发 ACK 报文。
等的时间正好 = 传过去 + 传回来的最大值。
-
TCP 客户端状态转换图:
客户端:从 CLOSED 态开始:
- 初始化 TCP 连接,发送 SYN,发起三次握手
- 收到 SYN & ACK,发送 ACK,发起 三次握手之三
- 收数据ing
- 发送 FIN,发起四次挥手
- 收到 ACK,不发任何东西(知道服务器端收到我的 FIN 报文了,让它把没发完的数据继续发)
- 收到 FIN,发送 ACK(此时服务器端的东西发完了)。继续等待 2*max segment time。发起 四次挥手之四
2 msl 后无响应则断开连接
-
TCP 服务器端状态转换图:
服务器端:从 CLOSED 态开始:
-
监听 LISTEN
-
收到 SYN,回复 SYN & ACK,发起 三次握手之二
-
收到 ACK,结束三次握手,开始收发数据
-
发数据ing
-
收到客户端的 FIN 报文,回复 ACK,发起 四次挥手之二
-
发剩下没法玩的数据ing
-
数据发完之后发送 FIN 报文,等待客户端的 ACK 。发起 四次挥手之三
超时后若没等到重新发 FIN 报文给客户端。
收到 ACK 后断开连接
-
-
-
拥塞控制
-
场景1:
-
假设两个发送者,两个接收者,一个路由器。不执行重发,带宽为 C。
-
每个主机最大可达吞吐量 C/2,但是拥塞时延在 C/2 时达到无限大!
-
-
场景2:
-
一个路由器,有限缓冲区
-
发送方重发丢失的报文
-
总是 λ i n = λ o u t \lambda_{in}=\lambda_{out} λin=λout (goodput)
-
超时而没有丢失的报文重发——同样的 λ o u t \lambda_{out} λout 需要比完美情况更大的 λ i n ′ \lambda_{in}' λin′
-
拥塞的代价:重发(更多的工作)得到更好的吞吐量
-
不必要的重发:链路需要运输多个分组的拷贝
-
-
-
场景3:
-
4个发送方、多跳路径、超时/重发
当 λ i n \lambda_{in} λin 和 λ i n ′ \lambda'_{in} λin′ 增加时,可能会发生以下情况:
- 拥塞增加:由于 λ i n \lambda_{in} λin 和 λ i n ′ \lambda_{in}' λin′ 的增加,网络中的数据流量变大,可能导致路由器或交换机的输出链路出现拥塞。
- 数据包丢失:拥塞会导致缓冲区溢出,从而导致数据包丢失。这种情况会导致需要重传数据,进一步增加 λ i n ′ \lambda_{in}' λin′。
- 延迟增加:随着数据包在网络中等待传输的时间增加,数据传输的延迟也会增加。
- 网络效率下降:由于重发数据的增加,有效数据传输的比例降低,整体网络效率可能下降。
- 多跳路径影响:在多跳路径的情况下,拥塞不仅会影响当前链路,还会波及到其他相关链路,可能导致更广泛的网络性能下降。
总结来说,当 λ i n \lambda_{in} λin 和 λ i n ′ \lambda_{in}' λin′ 增加时,会导致网络拥塞、缓冲区溢出(数据包丢失)、延迟增加和整体网络效率下降。这些都是由于共享输出链路的带宽限制以及数据重发引起的。
拥塞的另一个代价:当分组丢失后,任何上游路由器的发送能力都浪费了
-
-
拥塞控制的方法:
- 端到端拥塞控制:
- 没有从网络中得到明确的反馈
- 采用 TCP 拥塞控制(检测数据包的丢失和延迟来判断网络是否拥塞)
- 网络辅助的拥塞控制:
- 路由器通过单 bit 向端系统指示拥塞(使用一个位来指示网络中的拥塞状态)
- 指明发送者应该发送的频率
- 端到端拥塞控制:
-
3.7 TCP 拥塞控制
-
特点:
- 端到端控制(没有网络辅助)
- 发送方限制发送
- 大体上, r a t e = C o n g W i n R T T B p s rate=\frac{CongWin}{RTT}Bps rate=RTTCongWinBps ,其中 CongWin(Congestion Window,阻塞窗口)是动态的、感知的网络拥塞的函数。
-
发送方如何感知拥塞?
- 超时 or 3个重复的ACK = 丢失事件**(超时、收到3个重复的ACK 通常作为网络拥塞的标志)**
- TCP 发送方在丢失事件发生后降低发送速率(CongWin)
-
三个机制:
- 慢启动
- AMD:发送方增加发送速率,直到丢包发生,然后在丢包时再降低发送速率
- 对拥塞事件作出反应
-
具体参考:TCP的拥塞控制算法:慢启动算法、拥塞避免算法,快速重传与超时重传算法,快速恢复算法_tcp慢启动和拥塞避免-CSDN博客(前面的概念讲解可以看看,后面的 TCP 对丢包的处理和PPT不太一样)
-
必考一道大题
sshthresh
(slow start threshold,慢启动阈值)
-
怎样理解不同的丢包事件?
- 3个重复ACK表名网络具有传输一些数据段的能力
- 在三个重复的确认之前超时,那么说明网络传输能力差,更严重!
-
超时重传时的拥塞控制算法:
sshthresh=原CongWin/2
新CongWin=1
-
快速重传时的拥塞控制算法
sshthresh=原CongWin/2
对于CongWin的处理有两种方式:
- 新CongWin=1(Tahoe版本)
- 新CongWin=原CongWin/2 + 3(Reno版本),此时会直接进入拥塞避免状态
-
PPT例子:
-
三种考法:
-
用文字描述概念
-
画or分析 图/表格
-
给出图/表格,用文字描述事件(如 第8~9RTT发生什么事了?)
-
-
上图字有点小:
在线性增长阶段,一个 RTT 内,不论收到多少个ACK,CongWin都只会+1。慢启动阶段同理。
-
总结:
- 当CongWin低于阈值,慢启动,指数级增长
- 当CongWin高于阈值,拥塞避免,线性增长
- 快速重传(3次重复ACK)——阈值置为CongWin/2,CongWin置为1或者阈值+3
- 超时——阈值置为 CongWin/2 ,CongWin置为1
-
TCP 平均吞吐量:0.75 W/RTT
假设忽略慢启动
- 在丢失发生时窗口大小为 W,吞吐量是 W/RTT
- 丢失发生后,窗口降为 W/2,吞吐量为 0.5 W/RTT
- 则 平均吞吐量为 0.75 W/RTT
-
TCP 未来
-
例:1500字节的数据段,RTT=100ms,希望10Gbps吞吐量。要求窗口大小 W=83333个报文段。
-
按照一个连接的平均吞吐量公式(L为丢包率): 1.22 ∗ M S S R T T ∗ L \frac{1.22*MSS}{RTT*\sqrt{L}} RTT∗L 1.22∗MSS
则选择的TCP为到达 10 Gbps的吞吐量,要求 L = 2 ∗ 1 0 − 10 L=2*10^{-10} L=2∗10−10,即每500万个报文段只允许丢失一个报文段
用于高速的TCP的新版本时必要的
(照着PPT写的,应该不考)
-