- 第3章 传输层(Transport Layer)
- 3.1 传输层服务与协议
- 3.2 复用 分用
- 无连接的分用、复用(UDP)
- 面向连接的分用、复用(TCP)
- 持续/非持续HTTP连接 与 常见端口
- 3.3 无连接传输: UDP
- 3.4 可靠数据传输原理(rdt)
- rdt 1.0:经完全可靠信道的可靠数据传输
- rdt 2.0:发现并修复位差错
- rdt 2.1:数据包带序号
- rdt 2.2:ACK取代NAK
- rdt 3.0:超时重传 治疗数据包丢失
- 3.5 流水线技术(GoBackN & Selective Repeat)
- Go-Back-N
- 选择重传(Selective Repeat)
- 3.6 面向连接传输: TCP
- TCP可靠数据传输
- 3.7 流量控制(flow control)
- END 练习
第3章 传输层(Transport Layer)
传输层
== 运输层
套接字(Socket)
= IP地址
+ 端口号(port)
,位于应用层
3.1 传输层服务与协议
- 运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信 (logic communication) 功能
- 运输层协议是在端系统中实现。发送端将从发送应用程序进程接收到的报文分段(转换成运输层分组),传递给网络层;接收端将报文段重组成完整报文,传递给应用层。
- 关于 运输层 和 网络层 的关系:
1)网络层 负责在不同主机之间提供 逻辑通信 服务;
2)运输层 负责 通过网络层 进行不同主机的进程之间的 逻辑通信。 - 两种主要的网络传输协议:TCP 和 UDP
1)TCP:可靠、有序传输、拥塞控制、流量控制、连接建立
2)UDP:不可靠、不保序传输、没有为尽力而为的IP服务添加更多的其它额外服务
3)都不提供的服务:延迟保证、带宽保证
3.2 复用 分用
- 复用 / 多路复用(multiplexing):从源主机的不同套接字中收集数据块,并为每个数据块封装上首部信息(“传输头”),进而生成报文段,然后将报文段传递到网络层,就是 把多个数据流 (streams) 合并为一个数据流
- 分用 / 多路分解(demultiplexing):将运输层报文段中的数据交付到正确的套接字的工作,就是 复用的逆过程,数据流被分离成单独的部分,相当于解码。具体操作为:接收端的运输层标识出报文段中的接受套接字,进而将报文段定向到该套接字
- 多路复用和多路分解服务是所有计算机网络都需要的
理解:你的的手机正在浏览网页,刷新电子邮件,同时连接到微信。所有这些连接都通过同一链路发送,这一过程为复用;手机接收到的数据包流将被分割并发送到相应的网络、电子邮件、微信程序,该过程为分用
无连接的分用、复用(UDP)
- UDP Socket = (dstIP, dstPort)
UDP 套接字 = (目标IP地址 + 目标端口号) - 发送方创建UDP套接字的数据报时,必须指定 目标IP地址、目标端口,而且包含源端口号
(A send b-ip, b-port, a-ip, a-port to B,包含源端口号是为了 接受方B回发报文段给发送方A时,使用recvfrom()方法从发送方的UDP报文段中取源端口号的值,当然完整的返回地址为 源IP+源端口) - 接收方接收UDP报文段时,检查段中的目的端口,将UDP报文段定向到 具有指定目标端口的套接字
- 不同源IP地址或源端口号的数据报,具有相同目标端口,发送到同一个目标IP地址,会定向到同一目标套接字
面向连接的分用、复用(TCP)
- TCP socket = (sourceIP, sourcePort, destIP, destPort)
TCP 套接字 = (源IP地址 + 源端口号 + 目标IP地址 + 目标端口号) - 服务器主机支持许多并行的TCP套接字,每个套接字与 1 个进程/线程相联系,且由四元组来标识套接字
- (与UDP不同) 两个不同源IP地址或源端口号的数据报,即使具有相同的目标端口和目标IP地址,也会定向到不同的套接字
(若TCP报文段中包含 初始创建TCP连接的请求,接收方服务器会创建新的套接字)
参考上图3.5,主机A,Web服务器B,主机C的IP地址分别为A、B、C。主机C 与 服务器B 之间有两个HTTP会话连接,会话源端口号分别为7532、26145,目标端口号都为80,在服务器传输层 分用 至两个不同的套接字;主机A 与 服务器B 之间由一个HTTP会话连接,源端口号为26145,目标端口号为80,与主机A的其中一个会话源端口号相同,但在服务器传输层也会 分用 至两个套接字。(总结:每个套接字由其四元组标识;目标端口相同的数据被分用至不同的套接字)
持续/非持续HTTP连接 与 常见端口
- 持续HTTP:在整个连接持续期间,客户端与服务器之间 经由 同一个服务器套接字交换 HTTP报文
- 非持续HTTP:对每一对请求/响应都创建一个新的TCP连接和一个套接字并随后就关闭(这种套接字的频繁创建-关闭会严重影响服务器性能,即使可以通过操作系统技巧减轻影响)
- 常见端口:
Port 80:标准HTTP连接
Port 22:SSH 远程计算机而当路
Port 25:SMTP端口,邮件服务器使用的默认端口
Port 143:IMAP端口,接收电子邮件,类似与POP3
Port 443:标准HTTPS连接,安全
端口对比:Port 80 (HTTP) vs. Port 443 (HTTPS)
3.3 无连接传输: UDP
- UDP 协议 是 实现了端口的 IP协议,可以让数据包在送到某个IP地址的基础上,进而送到运行在某一端口的通信进程
UDP 协议是TCP 协议的简化版,出现于TCP之后
应用场景:直播等流媒体应用程序、域名系统DNS、NFS等 - UDP 协议的优点:简单、快、高效(Efficient)、没有拥塞控制;缺点:传输不可靠、尽力而为(Best Effort)、UDP报文段可能会丢包、乱序
- UDP 报文段(segment) = [ 源端口号,目标端口号,长度,校验和,应用程序数据 ]
length:以 bytes 为单位的UDP报文段长度,包含传输头(UDP Segment Header)的长度 和 原始数据(Payload)长度,其中 udpSegmentHeader = sPort+dPort+Length+CheckSum = 16 bits*4 = 8 bytes)
checksum:用于检测整个数据包是否损坏(包括整个UDP数据包,以及IP头部的源IP和目标IP等信息),没有改正能力,在IPv4中可以不使用checksum,即checksum为0 - 写者留:检验和 checksum 的具体计算方式还没写, 可以先看书 :)
3.4 可靠数据传输原理(rdt)
- 背景:期望每次信息传输都是理想状态是不太可能的,而且 "Best Effort"的 IP协议不会修复,传输自己时还可能产生错误或丢失,所以需要可靠数据传输(Reliable Data Transfer)
rdt 1.0:经完全可靠信道的可靠数据传输
rdt 2.0:发现并修复位差错
引入3种功能:
1. 通过 checksum 来校验错误
2. 接收者 反馈接受 ACK 和 NAK信息
3. 重传
理解:传输层对应用层的数据进行打包处理时,新增checksum(校验和),从而接收端可以对其数据包进行检验,如果正确,返回ACK,发送者继续发送下一个数据包;如果不正确,返回NAK,发送者重传数据。**
- rdt2.0 没有错误时的操作
- rdt2.0 发生错误时的流程
rdt 2.1:数据包带序号
- 背景:rdt2.0不能解决ACK和NAK出错的问题,重传可能会导致重复
- 解决:
① 发送方为每一个数据包添加 编号(seq)
② ACK / NAK出错,发送方重传
③ 接收方丢弃重复的数据包
④ “stop and wait” 停等机制,发送方发送一个包,等待接收方回应 - 机制:
rdt 2.2:ACK取代NAK
- 用 带序号的ACK 代替 ACK / NAK,接收方接收ACK信号时检查ACK的序号
- 机制
rdt 3.0:超时重传 治疗数据包丢失
- 问题背景:数据包或ACK丢失,可能会导致重传和数据重复
- 解决:超时重传
发送端在设定时间内没有收到指定编号的ACK则重传
重传虽然会导致数据重复,但可以通过序列号解决 - 机制:
3.5 流水线技术(GoBackN & Selective Repeat)
- 问题:1 Gbps link, 15ms 延迟, 8000bit 大小的包,将round-trip-time作为传播到那里和返回的时间(rtt,即两倍的end-to-end延时),传输延时和信道利用率是多少?
答: L L L-包大小; R R R-传输速率。
D t r a n s = L / R = 8000 b i t s 1 0 9 b i t / s = 8 m s D_{trans}=L/R=\frac{8000bits}{10^{9}bit/s}=8ms Dtrans=L/R=109bit/s8000bits=8ms
U s e n d e r = L / R R T T + L / R = 0.008 15 ∗ 2 + 0.008 = 0.027 % U_{sender}=\frac{L/R}{RTT+L/R}=\frac{0.008}{15*2+0.008}=0.027\% Usender=RTT+L/RL/R=15∗2+0.0080.008=0.027% - 流水线技术(Pipelining):允许发送方在未得到对方确认的情况下一次发送多个包
- 条件:
① 增加 包/应答 的序号范围
② 发送方 设置缓存(未得到确认,可能需要重传 ?)
③ 接收方 设置缓存(上层用户取用数据的速率≠接收到的数据速率;接收的数据包可能乱序;可能需要重新排序后交付)
Go-Back-N 与 Selective Repeat 过程动画演示
Go-Back-N
- 核心:sender能够在收到确认之前发送多个分组,但receiver只能缓存一个符合要求的分组并回复确认
- 发送方一次发送 N 个包
- 接收方 只缓存并确认 按顺序正确到达的包
- 发送方设置计时器,超时(没收到回应)重传
- 机制:
- 缺点:
Go-Back-N在一定程度上避免了停等协议中信道利用率低下的问题,但在窗口N较大时,Go-Back-N需要重传的包较多,代价大
选择重传(Selective Repeat)
- 核心:
① 接收方单独确认所有正确接受的包(不按顺序)
② 根据需要,将缓冲区中的包按顺序传给上层
③ 发送方仅发送 未收到ACK的包
④ 每个未确认的包都有计时器,超时重传 - 机制:
Sender:
① 收到上层数据,如果 发送窗格的下一个序号可用,打包发送
② packet(n) 超时,重发n号包,计时器重置
③ 收到 ACK(n),如果 n 是未确认的包中编号最小的,右移发送窗格
Receiver:
① 收到 packet(n)后,回复 ACK(n)
② 如果编号顺序乱/缺失,缓存并等待接受前面的包
③ 如果编号顺序正确,将包传给上层,移动 接收窗格
④ 重复的包直接丢弃
- 存在的问题:
- 设帧序号为0,1,2,3 重复使用但内容不同,窗格大小为3,传输过程如下图
- 当 receiver接受到 0,1,2号包之后,发送ACKs(0,1,2),移动接收窗格到 [3,0,1] 等待接收packet(3,0,1)。
如果 sender 没有在设定时间内接收到ACKs,会超时重传 packet(0,1,2)。
当 receiver 接收到 sender 重发的 packet(0,1)时,会认为它们是新一轮序号的包,并将其缓存(正常应该直接丢弃的包),造成二义性 - 解决:
① 发送窗格 <= 接受窗格
② 发送窗格大小 <= 1 2 ∗ \frac{1}{2}* 21∗序号数(n比特编码,发送窗格长度最大为 2 n − 1 2^{n-1} 2n−1)
- 设帧序号为0,1,2,3 重复使用但内容不同,窗格大小为3,传输过程如下图
3.6 面向连接传输: TCP
-
面向连接:只有在确认通信对端存在时才会发送数据,从而可以控制通信流量的浪费
-
TCP 报文段结构:
- 源端口号 / 目的端口号:16 bits
- 序号(sequence number):32 bits,段数据中第一个字节的在整个字节流中“编号”,用来标明位置
- 确认号(acknowledgements):32 bits,期望从对方收到的下一个字节的序号
-
具体应用:
-
超时时长的设置
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∣T i m e o u t = E s t i m a t e d R T T + 4 ∗ D e v R T T Timeout = EstimatedRTT + 4 * DevRTT Timeout=EstimatedRTT+4∗DevRTT
其中 R T T RTT RTT为 round-trip-time 往返时间; D e v R T T DevRTT DevRTT为 RTT偏差值(safety margin);
S a m p l e R T T SampleRTT SampleRTT为 报文段的样本RTT; E s t i m a t e d R T T EstimatedRTT EstimatedRTT为TCP对下一个数据往返值进行的估计
TCP可靠数据传输
-
实现:
- 收到上层应用层传来的数据
① 将数据划分为多个数据段,并编号Seq_num
② 编号Seq_num是该段中第一个数据字节在整个字节流的位置
③ 没开始前设置计时器,超时周期为 刚计算出得TimeOutInterval - 超时
重传导致超时的段,重启计时器 - 之前未确认过的段被确认了
① 标记它被确认了
② 设置计时器,继续传没被确认的段
- 收到上层应用层传来的数据
-
TCP 重传方案
-
快速重传
通过 重复的ACK 来检测报文段丢失:发送方通常连续发送大量报文段,如果报文段丢失,发送方一般会收到多个重复的ACK
如果发送方收到同一数据的3个重复ACK,重传对方需要的数据段(第一个ACK正常,后面三个为重复ACK)
3.7 流量控制(flow control)
- 背景:应用层从传输层socket中提取数据,然而往往数据不会提的这么快,这时候要是 sender 还一直发数据就会挤满 接收端的缓存(RcvBuffer),挤满后传输的数据就只能作废。
END 练习
-
问题:考虑一个可靠的数据传输(rdt)协议,通过一个有比特错误的信道(数据包被破坏但没有丢失)。解释检测错误并恢复的过程。
Q:Consider a reliable data transfer (rdt) protocol over a channel with bit errors (packets are corrupted but not lost). Explain the procedure to detect and recover from errors.
答:① 从数据包头部解析出校验和 checksum,② 通过数据包及头部计算新的校验和,③ 如果两者不匹配,则说明包错误,④ 接收方回应NAK(rdt2.1) 或 回应带有错误编号的ACK(rdt2.2/rdt3.0)
-
(往年考题) rdt2.1相关问题 (书 P191 第三章习题 P6):
考虑我们改正协议rdt2.1的动机。试说明如图3-57所示的接收方与如 图3-11 所示的发送方运行时,接收方可能会引起发送方和接收方进人死锁状态,即双方都在等待不可能发生的事件。P6. Consider our motivation for correcting protocol rdt2.1 . Show that the receiver, shown in
Figure 3.57 , when operating with the sender shown in Figure 3.11 , can lead the sender and
receiver to enter into a deadlock state, where each is waiting for an event that will never occur.
参考答案:
假设发送方(图3-11)处于“等待来自上层的调用1”状态时,而接收方(图3-57)处于“等待来自下层的1”,
发送方发送1号数据包,并转换到“等待ACK或NAK 1”状态,等待ACK或NAK。
现在假设接收方正确地接受了1号数据包,发送了ACK,然后转换到“等待来自下层的0”状态,等待0号数据包。
但是,若ACK消息损坏,rdt2.1发送方接收到损坏的ACK,条件rdt_rcv(rcvpkt)&&(corrupt(rcvpkt)为 True,
发送方会执行udt_send(sndpkt),重新发送1号数据包,而接收方在等待0号,has_seq1(rcvpkt)为 True,
在没接收到0号数据包时会始终返回NAK消息,而发送方处于当前状态时接收到NAK会始终发送1号数据包。
因此,发送方处于“等待ACK或NAK 1”状态,始终接收NAK并发送1号数据包,
接收方处于“等待来自下层的0”状态,始终接受1号数据包并丢弃,返回NAK,从而陷入死锁状态。
-
Go-Back-N 理解练习
Go-back-N 接收方收到了packets 1,2,3,5,下面说法正确的是:
A) 回复 ACKs 1,2,3,5
B) 发送 packets 1,2,3,5 给应用层
C) 不应该向应用层发送包,因为缺失了部分数据(4)
D) 应该丢弃 packet 5 ✓ \checkmark ✓ -
TCP快速重传练习
TCP sender 窗格大小为5,待发送包共10个,sender发送pkt(1,2,3,4,5)。当sender收到下列情况的ACKs时会执行什么操作?
① 收到 ACK(1,2,3,4,5)
② 收到 ACK(1,3)
③ 收到 4次 ACK1
答:① 正常发 pkt(6,7,8,9,10);② 发 pkt(6,7,8),等待pkt(4)是否超时(收到ACK3说明pkt2肯定收到,发送方窗格移动到[45678],pkt45已发,只需要发送pkt678即可);③ 重发pkt(2),正常发pkt(6)(本题ACK n的序号与现实传输不同,表示对n号包的确认,而不是需要sender的pkt-n;第一次ACK1表示收到了pkt-1,pkt-2传输时丢失,后三次ACK1分别来自receiver接收到pkt-3,4,5时的反馈,因为没收到pkt-2,只能回复确认pkt-1收到了;收到ACK1,sender窗格移动到[23456],可以正常发pkt-6)