-
3.1 概述和运输层服务
-
网络层 为网络中的两个端系统提供逻辑通信;运输层 为网络中两个端系统上的应用进程提供逻辑通信。
-
运输层 在端系统和路由器上都有实现。当进行端系统之间的通信时,路由器只起到转发分组的作用,因此可以将路由器看作只有底部三层协议栈。但是当路由器之间进行通信时,比如计算并更新转发表时,路由器也需要使用运输层协议,比如 RIP 使用 UDP,OSPF 使用 IP,BGP 使用 TCP。
-
-
3.1.1 运输层和网络层的关系
-
两个家庭孩子们收发信件的比喻
- 两个家庭分别位于美国东海岸和美国西海岸,每家有 12 个孩子。东海岸家庭的孩子们是西海岸家庭孩子们的堂兄弟姐妹。这两个家庭的孩子们喜欢彼此通信,每个家庭的每个人每星期要向另一个家庭的每个人写一封信,每封信用单独的信封通过传统的邮政服务传送。因此,每个家庭每星期要向另一个家发送 144 封信。每一个家庭有个孩子负责收发邮件,西海岸是 Ann 而东海岸家庭是 Bill。每星期 Ann 去她的所有兄弟姐妹那里收集信件,并将这些信件交给每天到家门口来的邮政服务的邮车上。当信件到达西海岸家庭时,Ann 负责将信件分发到她的兄弟姐妹手上。在东海岸家庭中的 Bill 也负责类似的工作。
- 应用层报文 = 信封上的字符
- 进程 = 堂兄弟姐妹
- 主机 = 家庭
- 运输层协议 = Ann 和 Bill
- 网络层协议 = 邮政服务(包括邮车)
- 多路复用 = Ann 和 Bill 去收集信件
- 多路分解 = Ann 和 Bill 去分发信件
- 两个家庭分别位于美国东海岸和美国西海岸,每家有 12 个孩子。东海岸家庭的孩子们是西海岸家庭孩子们的堂兄弟姐妹。这两个家庭的孩子们喜欢彼此通信,每个家庭的每个人每星期要向另一个家庭的每个人写一封信,每封信用单独的信封通过传统的邮政服务传送。因此,每个家庭每星期要向另一个家发送 144 封信。每一个家庭有个孩子负责收发邮件,西海岸是 Ann 而东海岸家庭是 Bill。每星期 Ann 去她的所有兄弟姐妹那里收集信件,并将这些信件交给每天到家门口来的邮政服务的邮车上。当信件到达西海岸家庭时,Ann 负责将信件分发到她的兄弟姐妹手上。在东海岸家庭中的 Bill 也负责类似的工作。
-
运输层协议受制于网络层协议,网络层协议不保证那么运输层也不能保证,比如时延上界和最小带宽。
-
即便网络层协议不提供,运输层也能支持,比如可靠数据传输(通过流量控制,序号,确认和定时器),安全性保证。
-
运输层还为整个因特网提供了服务:拥塞控制。
-
-
3.1.2 因特网运输层概述
-
UDP 提供不可靠,无连接的服务,TCP 提供可靠的,面向连接的服务。
-
UDP 仅提供 进程到进程的数据交付(复用/分解服务)、差错检查 这两种最低限度的运输层服务。
-
TCP 提供 进程到进程的数据交付(复用/分解服务)、差错检查 、可靠数据传输、拥塞控制 服务。
-
TCP 拥塞控制防止任何一条 TCP 连接用过多流量来淹没通信主机之间的链路和交换设备,力求为每条连接平等地共享网络链路带宽。UDP 流量则是不可调节的,使用 UDP 的应用程序可以用任何速率来发送数据。
-
-
3.2 多路复用与多路分解
-
多路分解 : 将运输层报文段中的数据交付到正确的套接字的工作
-
多路复用 : 从不同套接字中收集数据块,为每个数据块封装上首部信息从而生成报文段,然后将这些报文段传递到网络层的工作。
-
无连接的
多路复用
与多路分解
- UDP 套接字使用二元组
(目的 IP、目的端口)
来标识,即使两个报文段源端口
和源 IP
不一样,只要目的 IP
和目的端口
一样,就会被定位到目的主机上相同的 UDP 套接字。 - 例子 : 两个 B 主机上的进程(源端口号不同)向 A 的同一个端口发送 UDP 报文,会被 A 定位到相同的 UDP 套接字。
- UDP 套接字使用二元组
-
面向连接的
多路复用
与多路分解
- TCP 套接字使用
(目的 IP、目的端口、源 IP、源端口)
来标识,如果两个报文段源IP 或者源端口
不同,即使目的 IP 或者目的端口
相同,也会被定位到不同的 TCP 套接字。 - 例子 : 两个 B 主机上的进程(源端口不同)向 A 同一个端口发送 TCP 报文,会被 A 定位到不同的 TCP 套接字。
- 感觉 欢迎套接字 是使用
(目的 IP、目的端口)
来标识的,因为源端口
和源 IP
不同的报文段都会被定位到该套接字上。
- TCP 套接字使用
-
-
3.3 无连接运输:UDP
-
UDP 是 无连接 的,因为 UDP 没有握手阶段,不会为这次 UDP 通信过程维护状态变量。
-
选择 UDP 的理由
-
应用层对何时、发送什么数据可以控制得更为精细
-
1、TCP 发送数据时,先将数据放入发送缓冲区,然后再从发送缓冲区中拿出一块数据,附上运输层首部字段成为 TCP 报文段,再进行发送。从缓冲区中拿出的数据可能会多也可能会少,这取决于 MSS、流量控制 以及拥塞控制、以及应用层往 TCP 套接字中注入数据的速率等几个方面。而 UDP 不一样,无论应用交给 UDP 多长的数据,UDP 都将它压缩在一个报文段内发送(
⚠️ UDP 的首部字段中描述长度信息的域仅为两个字节,即最大 UDP 包为 65535 字节)。因此应用程序对在报文段中发送什么数据有更多的控制。 -
2、TCP 的拥塞控制会遏制发送方的速率。
-
3、发生丢包或失序时 TCP 发送方会重传而不管可靠交付需要用多长时间,因此在能容忍部分丢失和希望有最小发送速率的实时应用上,TCP 并不适合。
-
-
无需连接建立:不会引入建立连接时延,两个 RTT。
-
无连接状态:接收双方无需为连接状态维护状态变量,比如接收和发送缓存,拥塞控制参数、序列号、确认号参数。
-
分组首部开销小:TCP 20 字节首部开销,UDP 8 字节。
-
-
⚠️ 为了安全原因,很多防火墙被配置为阻塞 UDP 流量,因此对于图像和音视频流量,很多是建立在 TCP 之上的。 -
3.3.1 UDP 报文段结构如下
-
3.3.2 UDP 校验和代码实例如下
-
⚠️ 这种方法只能检测出所有 1 比特的差错,如果同时出现 2 比特以上的差错,可能无法被校验出来。比如 0010,0001 变为 0011,0000。在改变前后这两个 4 比特数的加和相同。
-
-
-
3.4 可靠数据传输原理:
-
基于假设:分组将以发送的次序进行交付,某些分组可能会丢失,但底层信道不会对分组重排序
-
⚠️ 如果分组重新排序会发生,那么一个具有序号或确认号 x 的分组的旧副本可能会出现,即使发送方或接收方的窗口中都没有包含 x,实际中采用的处理方法是,确保一个序号不被重新使用,直到发送方 “确信” 任何先前发送的序号为 x 的分组都不再在网络中为止。通过假定一个分组在网络中的 “存活” 时间不会超过某个固定最大时间量来做到这一点。在高速网络的 TCP 扩展中,最长的分组寿命被假定为大约 3 分钟。 -
3.4.1 构造可靠数据传输协议
-
- 底层信道可靠: rdt 1.0
-
- 比特差错:
-
rdt 2.0 (未考虑 ACK 或 NAK 包也会损坏)
-
rdt 2.1 (考虑到 ACK 和 NAK 也会损坏,那么采用的解决方法是:若发送方收到损坏的分组,就重传当前数据分组。但是冗余分组又引入了新的问题,如下所述)
-
⚠️ 冗余分组的根本困难在于:当发送方收到损坏的分组 (可能是 ACK 也可能是 NAK),发送方简单重传当前数据分组即可,但是在接收方看来,它并不知道上次所发送的 ACK 或 NAK 是否被发送方正确地接收到 (发送方可能收到一个损坏的,或未损坏的确认,接收方对此并不知情),因此,接收方无法判断它接收到的分组是新分组还是重传,如果接收方误判了一个新分组为重传,那么它忽略这个分组,交付给应用层的数据便产生了丢失,如果误判重传为新分组,那么交付给应用层的数据便产生了冗余。 -
解决方法:在数据分组中添加新字段 —— 序号,接收方只需检查序号便可得知到达的分组是重传还是新分组。对于停等协议,1 比特序号就足够了。这样的话,当接收方重复接收到序号为 0 的分组,它知道先前向发送方发送的对 0 分组的确认报文已经损坏,于是它重传对 0 分组的确认报文。对于发送方来说,它刚刚发送了 0 分组,但却得到接收方回传的一个损坏的确认报文,这个报文本来可能是 ACK,也可能是 NAK,发送方不能断定 0 分组是否被接收方正确接收,于是它不断重传 0 分组。直到收到一个未损坏的对 0 分组的 ACK 报文。
-
rdt 2.2 (考虑了 ACK 和 NAK 会损坏的情况,不使用 NAK 而是使用 带序号的 ACK)
-
rdt 2.1 的接收方当收到损坏分组时向发送方回传一个 NAK,但不用 NAK,而是对上次正确接收的分组发送一个 ACK,也能达到同样的效果。发送方本来在等待 ACK 0,却等来了 ACK 1,那么它便知道它发送的 0 分组没有被接收端正确接收,于是它选择重传 0 分组。对于接收方,若它已经成功接收了 0 分组,但是它又收到 0 分组,它便知道它发送的 ACK 0 没有被发送方正确接收,于是它选择重传 ACK 0 报文。
-
- 比特差错、丢包:rdt 3.0
-
-
3.4.2 流水线可靠数据传输协议
- 定义发送方的信道利用率为:发送方实际忙于将比特发送进信道的那部分时间与发送时间之比。从下图可以看出
stop-wait
具有极低的信道利用率,因此采用流水线技术改善信道利用率。
- 采用流水线技术对可靠数据传输协议带来如下影响:
-
必须增加序号范围,每个传输中的分组必须有一个唯一的序号,而且也许有许多个在输送中未确认的报文。
-
协议的发送方和接受两端也许必须缓存多个分组。发送方最低限度应当能缓存那些已发送但没有确认的分组。接收方或许也需要缓存那些已正确接受的分组。
-
所需序号范围和对缓存的要求取决于如何处理丢失、损坏及延时过大的分组。流水线差错恢复有两种基本方法:回退 N 步 (Go-Back-N, GBN) 和 选择重传 (Selective Repeat, SR)
-
- 定义发送方的信道利用率为:发送方实际忙于将比特发送进信道的那部分时间与发送时间之比。从下图可以看出
-
3.4.3 回退 N 步
-
试玩该交互动画并体会 GBN 的每个细节。GBN interactive-animation
-
-
3.4.4 选择重传
-
试玩该交互动画并体会 SR 的每个细节 SR_interative-animation
-
SR 发送方的事件与动作
-
从上层收到数据。若序号在窗口内,则将数据打包发送;否则要么将数据缓存,要么返回给上层以便以后传输。
-
超时。定时器用来防止分组丢失,每个分组都有自己的定时器,因为超时发生时只能发送一个分组。
-
收到 ACK。若分组序号在窗口内,SR 将该分组标记为已接收,如果该分组序号等于
send_base
,则窗口的send_base
移动到最小未确认序号处,如果窗口移动了并且新窗口内有未确认分组,则发送这些分组。
-
-
SR 接收方的事件与动作
-
序号在
[rcv_base, rcv_base + N - 1]
内的分组被正确接收。若收到分组在窗口内,则回传一个ACK
给发送方。如果以前没接收过,缓存该分组。若分组序号等于recv_base
,则将从recv_base
开始连续的分组交付给上层,然后窗口向前移动。 -
序号在
[recv_base - N, recv_base - 1]
内的分组被正确收到。必须产生一个ACK
给发送方,即使该分组是接收方以前已经确认过的分组。(因为窗口滑动顺序永远是接收方提前于发送方,如果接收方已经收到该分组(此时接收方的窗口也许已经滑动),但不回传 ACK 的话,发送方的窗口将永远不能向前滑动), 为什么会接受到[recv_base - N, recv_base - 1]
范围内的分组?试想下列情况:接收方正确接收到0 ~ k
的分组,并回传0 ~ k
的确认,但这些确认报文丢失了序号最小的一个,或者丢失了全部,此时发送方的窗口无法向前滑动,发送方正等待超时重传,重传的分组就会落在接收方[recv_base - N, recv_base - 1]
的范围内。 -
其他情况。忽略该分组
-
-
SR 的问题
-
-
-
3.5 面向连接的运输:TCP
-
3.5.1 TCP 连接
-
TCP 被称为是 面向连接的,这是因为建立 TCP 连接必须先收发握手报文,发送方和接收方都在发送报文时初始化 TCP 的状态变量(比如套接字、接收缓存、发送缓存、LastByteRecved、LastByteSent、LastByteAcked、LastByteRead 等)。
-
TCP 面向连接仅仅指的是在端系统中维护与 TCP 连接有关的状态变量,而不是说在发送方和接收方沿途的路由器和通信链路中维护有该连接的状态信息,实际上,中间路由器对连接视而不见。
-
TCP 连接提供全双工服务:即 A 主机上进程 a 向 B 主机上进程 b 通过同一条 TCP 连接发送数据时,b 也可以同时在该条 TCP 连接上将数据发给 a,TCP 连接总是点对点(单个发送方和单个接收方),而非多播(一个发送方,多个接收方)。
-
MSS (Maximum Segment Size) 和 MTU (Maximum Transmission Unit):MTU 指发送主机发送的最大链路层帧长度,MSS 指的是单个 TCP 报文段允许容纳的最大应用层报文长度,MSS 受制于 MTU,一般 TCP/IP 报文首部字段总共 40 字节,所以假如 MTU 为 1500 字节,那么 MSS 为
MTU - 40 = 1460
字节。 -
TCP 构件的图示如下:
-
-
3.5.2 TCP 报文段结构:
- Telnet: 序号和确认号的一个学习案例
-
3.5.3 往返时间的估计与超时
-
估计往返时间
-
设置和管理重传超时间隔
-
超时间隔应该大于等于
EstimatedRTT
,否则将造成不必要的重传。但是超时间隔不应该比EstimatedRTT
大太多,否则当报文段丢失时,TCP 不能很快地重传该报文段,导致数据传输时延大。因此要求将超时间隔设为EstimatedRTT
加上一定余量,当SampleRTT
值波动大时,这个余量大一些;当波动小时,这个余量小一些。 -
TimeoutInterval = EstimatedRTT + 4 x DevRTT
-
-
-
3.5.4 可靠数据传输
-
简化的 TCP 发送方
NextSeqNum = InitialSeqNumber SendBase = InitalSeqNumber loop (forever) { switch(event) event: data received from application above create TCP segment with sequence number NextSeqNum if (timer currently not running) start timer pass segment to IP NextSeqNum = NextSeqNum + length(data) break; event: timer timeout retransmit not-yet-acknowledged segment with smallest sequence number start timer break; event: ACK received, with ACK field value of y if (y > SendBase) { SendBase = y if (there are currently any not-yet-acknowledged segments) start timer } else { /* a duplicate ACK for already ACKed segment */ increment number of duplicate ACKs received by y if (number of duplicate ACKs received for y == 3) /* TCP fast retransmit */ resend segment with sequence number y } break; } /* forever 循环结束 */
-
一些有趣的情况
-
超时间隔加倍
- 每当超时事件发生,TCP 重传具有最小序号的还未被确认的报文段。只是每次 TCP 重传时都会将下一次的超时间隔设为先前的两倍,而不是用从
EstimatedRTT
和DevRTT
推算出的值。
- 每当超时事件发生,TCP 重传具有最小序号的还未被确认的报文段。只是每次 TCP 重传时都会将下一次的超时间隔设为先前的两倍,而不是用从
-
快速重传
- 超时出发重传存在的问题之一是超时周期可能相对较长。当一个报文段丢失时,这种长超时周期迫使发送方延迟重传丢失的分组,因而增加了端到端时延。其实完全可以在超时事件发生之前通过注意到冗余 ACK 来较好地检测到丢包情况。如果 TCP 发送方姐收到对相同数据的 3 个冗余 ACK,就说明跟在这个已被确认 3 次的报文段之后的报文段丢失,此时,TCP 执行快速重传。
-
是回退 N 步还是选择重传?
- TCP 确认是累积式的,正确接收但失序的报文段是不会被接收方逐个确认的,因此,TCP 发送方仅需维持 已发送但未被确认的字节的最小序号 (SendBase) 和 下一个要发送的字节的序号 (NextSeqNum)。此时 TCP 看起来更像一个 GBN 风格的协议,但是许多 TCP 的实现会将正确接收但失序的报文段缓存起来,因此当 GBN 协议发送方未接收到对于
n
的确认时,会重传n,n+1,n+2,n+3 ...
的所有已发送但未确认报文,但是 TCP 只会重传n
。对 TCP 提出的一种修改意见是所谓的选择确认,它允许 TCP 接收方有选择地确认失序报文段,而不是累积地确认最后一个正确接收的有序报文段。此时 TCP 看起来又像 SR 协议。因此,TCP 的差错恢复也许最好被分类为 GBN 协议与 SR 协议的混合体。
- TCP 确认是累积式的,正确接收但失序的报文段是不会被接收方逐个确认的,因此,TCP 发送方仅需维持 已发送但未被确认的字节的最小序号 (SendBase) 和 下一个要发送的字节的序号 (NextSeqNum)。此时 TCP 看起来更像一个 GBN 风格的协议,但是许多 TCP 的实现会将正确接收但失序的报文段缓存起来,因此当 GBN 协议发送方未接收到对于
-
-
3.5.5 流量控制
-
试玩该交互式程序,并体会其中细节 flow-control_interactive_animation
-
⚠️ 注意区分 流量控制 和 拥塞控制 !!- 拥塞控制:TCP 发送方因为 IP 网络的拥塞而被遏制。
- 流量控制:消除发送方使接收方缓存溢出的可能性,即使发送方的发送速率和接收方接收速率相匹配。
-
TCP 通过让发送方维护一个称为 接收窗口 的变量来提供流量控制。该 接收窗口 用于给发送方一个提示 —— 该接收方还有多少可用的缓存空间。
-
发送方需要保证发送速率在该连接的整个生命周期内满足下列不等式约束:
LastByteSent - LastByteAcked <= RcvBuffer - [ LastByteRcvd - LastByteRead ]
即LastByteSent - LastByteAcked <= rwnd
-
流量控制 的注意点
-
若接收方的接收缓存已经存满,使得
rwnd = 0
, 在将rwnd = 0
通告给发送方后,此时假设接收方不会传送数据给发送方,那么发送方将不能知道接收方何时接收缓存中腾出了空闲空间出来。为了解决该问题,TCP 规范中要求:当接收方接收窗口为 0 时,主机 A 继续发送只有一个字节数据报文段。这些报文段将会被接收方确认。等到缓存开始清空,接收方回传的确认报文里将包含一个非 0 的rwnd
值。 -
UDP 不提供流量控制,因此会导致缓存溢出,最终丢失报文。
-
-
-
3.5.6 TCP 连接管理
- TCP 三次握手
- TCP 四次握手
-
-
3.6 拥塞控制原理
-
丢包一般是当网络变得拥塞时由于路由器缓存溢出引起的,分组重传因此作为网络拥塞的征兆。
-
3.6.1 拥塞原因与代价
-
分组的到达速率接近链路容量时,分组经历巨大的排队时延。
-
发送方必须执行重传以补偿因为缓存溢出而丢失的分组。
-
发送方遇到大时延所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本,而路由器本可以利用链路的传输能力去发送另一个分组。
-
当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了,第一跳路由器所使用的将分组转发到第二条路由器的传输容量本可以用来传送不同的分组 (例如:当选择一个分组发送时,路由器最好优先考虑那些已经历过一定数量的上游路由器的分组)。
-
-
3.6.2 拥塞控制方法
-
端到端拥塞控制:在端到端拥塞控制方法中,网络层没有为运输层拥塞控制提供显示帮助。TCP 必须通过端到端的方法来解决拥塞,因为 IP 层不会向端系统提供有关网络拥塞的反馈信息。
-
网络辅助的拥塞控制:在网络辅助的拥塞控制中,网络层构件 (即路由器) 向发送方提供关于网络中拥塞状态的显式反馈信息。
- 直接反馈信息可以由网络路由器发给发送方
- 路由器标记或更新从发送方流向接收方的分组中某个字段来指示拥塞的产生。一旦收到一个标记的分组后,接收方就会向发送方通知该网络拥塞指示。
-
-
3.6.3 网络辅助的拥塞控制例子:ATM ABR 拥塞控制
-
-
3.7 TCP 拥塞控制
-
如果一个 TCP 发送方感知从它到目的地之间的路径上没有拥塞,则 TCP 发送方增加其发送速率;如果发送方感知沿着该路径有拥塞,则发送方就会降低其发送速率。但是这种方法提出了三个问题:
-
TCP 发送方是如何限制向其连接发送流量的?
-
TCP 连接的每一端都由接收缓存、发送缓存和几个变量组成。TCP 通过维护一个额外变量 拥塞窗口 cwnd 来限制一个 TCP 发送方能向网络中发送的流量。特别是,在一个发送方中未被确认的数据量不会超过 cwnd 与 rwnd 中的最小值,即:
LastByteSent - LastByteAcked <= min{ cwnd, rwnd }
-
-
一个 TCP 发送方如何感知从它到目的地之间的路径上存在拥塞呢?
- 我们将一个 TCP 发送方的 “丢包事件” 定义为:要么出现超时,要么收到来自接收方的 3 个冗余 ACK。当出现过度拥塞时,在沿着这条路径上的一台或多台路由器的缓存会溢出,引起一个数据报(包含一个 TCP 报文段)被丢弃。丢弃的数据报会引起发送方的丢包事件(要么超时或收到 3 个冗余 ACK),发送方就认为在发送方到接收方的路径上出现了拥塞的指示。
-
当发送方感知端到端的拥塞时,采用何种算法来改变其发送速率呢?
-
慢启动
- cwnd 的值以 1 个 MSS 开始并且每当传输的报文段首次被确认就增加一个 MSS,因此,TCP 发送速率起始慢,但在 慢启动 阶段以指数增长。
- 何时结束慢启动?
- 若出现超时指示的丢包事件
--->
重新开始慢启动 - 发送速率超过 ssthresh
--->
拥塞避免 - 监测到 3 个冗余 ACK
--->
快速恢复
- 若出现超时指示的丢包事件
-
拥塞避免
- 线性增加而非指数增加拥塞窗口
- 何时结束 拥塞避免?
- 若出现超时指示的丢包事件
--->
重新开始 慢启动 - 监测到 3 个冗余 ACK
--->
快速恢复
- 若出现超时指示的丢包事件
-
快速恢复
- 何时结束 快速恢复?
- 若出现超时指示的丢包事件
--->
重新开始 慢启动 - 接收到缺失报文的 ACK
--->
拥塞避免 - 接收到缺失报文的冗余 ACK
--->
cwnd 增加一个 MSS,重新开始 快速恢复
- 若出现超时指示的丢包事件
- 何时结束 快速恢复?
-
TCP 拥塞控制:回顾
-
对 TCP 吞吐量的宏观描述
一条 TCP 连接的平均吞吐量 = (0.75 x W) / RTT
-
经高带宽路径的 TCP
一条 TCP 连接的平均吞吐量 = (1.22 x MSS) / (RTT x sqrt(L)),L 表示丢包率
-
公平性与 TCP
-
公平性与 UDP
- UDP 没有内置的拥塞控制,因此 UDP 源有可能压制 TCP 流量。
-
公平性与并行 TCP 连接
- 当一个应用使用多条并行连接时,它占用一条拥塞链路中较大比例的带宽。比如一条速率为 R 且支持 9 个在线客户-服务器应用的链路,如果新应用加入并使用一条 TCP 连接,则每个应用得到差不多相同的传输速率 R/10。但是如果这个新的应用使用 11 个并行 TCP 连接,则这个新应用就不公平地分到超过 R/2 的带宽。
-
-
-