《计算机网络》课程笔记 (Ch03-运输层)
为运行在不同主机上的应用进程之间提供逻辑通信功能。
将应用层报文切分为块,然后加上运输层首部,形成报文段,交付给网络层。
多路复用与多路分解
将网络层提供的主机到主机交付服务延伸到进程到进程交付服务。利用的是端口。
每个报文段有(源端口,目的端口)字段指示报文段要交付的套接字。当一个网络应用程序运行时,必须为其分配一个端口号。套接字与进程之间不一定一一对应,有的进程可以拥有多个套接字。
UDP下无连接的多路复用与多路分解
标识为<目的IP,目的端口>。来、回的报文段会发生端口号的反转。
TCP下面向连接的多路复用与多路分解
标识为<源IP,源端口,目的IP,目的端口>。对同一个目的端口的连接(如HTTP的80),根据源IP进行区分。
无连接运输UDP
用户数据报协议,只是做了传输协议能够做的最少的工作。
报文段结构
UDP校验和
对UDP报文段中所有16比特字求和,求和时遇到任何溢出都回卷(溢出位加到最低位),然后全部取反运算。
接收方将受到的全部的比特字(包括校验和)一起相加。如果分组中无差错,则这个和将是1111 1111 1111 1111;如果有1个比特是0,则说明分组中出现了差错。
只提供差错检测,不提供差错恢复。
可靠传输原理
如何在不可靠的信道上实现可靠传输?
四个事件
- rdt_send:上层调用,可靠发送
- udt_send:该层调用,不可靠发送
- rdt_rcv:该层调用,可靠接收
- deliver_data:该层调用,将数据送往上层
RDT 1.0 - 完全可靠信道
没有比特错误,没有丢包。
RDT 2.0 - 比特差错信道
引入校验和用来检测比特差错。引入确认机制(ACK和NAK)作为接收方的反馈消息,发送方收到NAK后重传。ACK和NAK不出错。
RDT 2.1 - ACK / NAK本身会出错
如果ACK/NAK出错,那么发送者直接重传当前的分组。
问题是引入了冗余分组,接收者无法分辨当前接收的是新分组还是重传的分组。解决方案是给分组添加序号,接收者收到相同序号的分组则认为是重传。
RDT 2.2 - 无NAK
ACK带序号,表示对对应分组的确认。如果发送方收到的是对上一个分组的ACK,则表示接收方没有正确接收当前分组,需要进行重传。
RDT 3.0 - 比特差错且丢包信道
由于新增了丢包问题,因此在RDT2.2的基础上新增倒数定时器用于进行定时重传。
在send pkt后一段时间若未收到ACK(说明pkt丢失或ack丢失),则重传pkt。
可能带来的问题是提前重传(ack还在路上),需要设置合适的timeout时间。
流水线传输
RDT3.0是一个停等协议,故存在性能问题,我们希望可以不停等方式运行,即允许发送方发送多个分组而无需等待确认。这要求增加序号范围;发送方和接收方要缓存多个分组。
解决流水线传输的差错回复主要有以下两种方法:
回退N步(GBN)
流水线中未确认的分组数不能超过N,即维护一个大小为N的窗口,发未ack的必须小于等于N。
接收方采用累积确认ACK,即收到ACK x时,x及小于x的分组均ACK。 这也意味着,如果发送方发送了1、2、3,接收方只收到1、3,则不可ACK 3,只能ACK 1。当超时发生时,发送方重传所有发未ACK的分组。
选择重传(SR)
收发双方都维护一个长度为N的窗口。发送方的窗口左不能大于最早的发未ack,接收方的窗口左不能大于最早的期待但未收到,即所有pending中的分组都必须在窗口中。
相比GBN,发送方只重传那些它怀疑在接收方出错的分组,从而避免单个分组的出错引起大量分组的重传。但这样,每个分组逻辑上都要有单独的定时器。
接收方在收到乱序分组时不丢弃而是缓存。在一段时间后发送方定时器将发现没有对应ack,从而怀疑丢失,进行重传。接收方收到缺失分组后补齐交付上层。
序号空间与窗口大小
窗口大小必须小于等于序号空间的一半。窗口大小过大会导致无法区分是新的分组还是之前重传的分组(序号空间已经轮完一轮)。
面向连接的运输TCP
基本介绍
特点:一对一,全双工(一端可同时收发),流水线,面向字节流,可靠传输。有流量控制和拥塞控制。
MSS(最大报文段长度(不含头部))限制了报文段的payload。
-
序号SEQ:该报文段首字节在有序的字节流中的编号
-
确认号ACK:期望从对方收到的下一个报文段首字节的序号
- 累计确认策略:对于失序的报文段, ACK该报文段的序号
-
RTT估计
超时重传的时间间隔必须大于RTT(往返时间,即报文段发出到确认的时间),因此估计RTT很重要。
使用指数加权平均来更新RTT的估计值:EstRTT=(1-α)EstRTTold+αSampleRTT,α=0.125,SampleRTT为采样的RTT
同时估计一个参数RTT偏差:DevRTT=(1-β)DevRTTold+β|SampleRTT-EstRTTold|,β=0.25来衡量RTT的波动
这样就可以给出超时间隔Timeout=EstRTT+4DevRTT
-
可靠数据传输实现
使用滑动窗口、累计确认、单个重传定时器、在超时或重复ACK时触发重传
-
场景1:仅超时重传
- 从上层应用接收数据,启动定时器(如果未启动)
- 定时器超时时,重传引起超时的报文段(最早发出未确认),重启定时器
- 超时后如何设置新的超时间隔?可以加倍。但当收到上层数据或ACK时,要重新按照公式计算。
- 收到ACK时,进行累计确认;如果此时仍有未确认的,则重启定时器
-
场景2:快速重传:超时或冗余ACK重传
冗余ACK:接收方送来一个之前发送方确认过的ACK,表明该期望包没有收到
快速重传的做法是收到3个冗余ACK就立即重传,不等待超时
-
流量控制
发送方太快可能淹没接收方,因此需要流量控制。(注意对比和拥塞控制的区别)
接收方维护变量接收窗口rwnd, 用于告诉发送方当前还有多少可用的缓存空间。发送方已发送未确认的数据量必须小于等于接收方当前的接收窗口,即LastByteSent-LastByteAcked≤rwnd。(全双工通信时,发送方同时是接收方,两端都需要维护rwnd)
连接管理
三次握手
流程:SYN x → ACK x+1, SYN y → ACK y+1
在这个过程中,完成了连接的建立和序列号的协商
四次挥手
流程:FIN x → ACK x+1 → FIN y → ACK y+1
ACK x+1后不立即FIN:发送残余数据
ACK y+1后不立即CLOSE,而是等2MSL:客户端发送的最后一个ACK可能丢失。假设丢失发生,则1MSL后,服务器因没收到ACK而重传FIN;又1MSL后,新FIN到达客户端,客户端重新执行ACK y+1。
TCP还设有一个保活计时器。客户端如果故障,服务器不能一直等。服务器每收到一次客户端的请求后都复位这个计时器。
拥塞控制
太多数据被发送到网络中, 网络来不及处理。表现是丢包和延迟。
拥塞控制站在网络角度,不同于流量控制的双方角度。
拥塞的代价
参数:λin - 分组到达速率;λout - 分组退出速率;R - 链路承载量
-
网络拥塞的一种代价:当分组到达速率接近链路容量时,将经历较长的排队时延。
2发2收,路由无限缓存,不重传。左图λout变平是因为超出的包全部丢掉了。
-
网络拥塞的第二种代价:发送方必须重传以补偿因为缓存溢出而丢弃的分组。
网络拥塞的第三种代价:发送方在遇到大时延时进行的不必要重传,导致路由器转发不必要的分组。
路由有限缓存,重传超时分组(丢失或太慢的)。则即使λin=λout,若考虑丢包重传,则λin'=λin+λforloss>λout,将发生拥塞。
理想情况下,若能区分且只重传丢失分组,则λout最终仍可到达R/2,即链路仍合理满载,因为相当于恰补足了丢失的部分,而没有多余的包。
实际情况下,不能区分丢失分组和太慢分组,会多重传(不必要重传),则链路无法合理满载。
-
网络拥塞的第四种代价:当分组被丢弃时,每个上游路由器用于转发该分组使用的传输容量最终浪费了。如果路由器R处理两条链路,其中一条超载,则另一条几乎不通。如果超载的这一条传输的数据在后级又被丢弃,则整个网络吞吐量将趋于0。
处理方法
端到端拥塞控制:让发送方根据感知到的网络拥塞,来调整发送数据的速率。
-
如何感知拥塞?
- 发生丢包事件(超时、冗余ACK)则网络拥塞
- 正常收到未确认的ACK则网络正常
-
如何限制发送速率?
- 维护一个变量拥塞发送窗口cwnd
- 约束LastByteSent-LastByteAcked≤min{cwnd, rwnd}
-
用什么算法调整发送速率?
-
基本思想
- 加性增:每经过1RTT,cwnd扩大1MSS,直到发生丢包
- 积性减:一旦发生丢包,cwnd减半
-
具体方法
-
慢启动:慢速率开始,指数级增长
-
cwnd=1MSS。每收到一个非冗余ACK,cwnd+=1,相当于每个RTT,cwnd*=2。
-
当cwnd到达阈值ssthresh时,转入拥塞避免模式(线性增长)
-
当发生超时时,修正阈值ssthresh=cwnd/2,cwnd=1MSS,重新慢启动
-
当收到3个冗余ACK时,修正阈值ssthresh=cwnd/2,cwnd=ssthresh+3,转入快速恢复模式
-
-
拥塞避免:加性增
- 从慢启动转向拥塞避免的条件可以知道,进入拥塞避免状态时,cwnd≈上次拥塞时的一半,则此时还没有拥塞,但不能过激增加
- 每个RTT,cwnd+=1
- 当发生超时时,修正阈值ssthresh=cwnd/2,cwnd=1MSS,重新慢启动
- 当收到3个冗余ACK时,修正阈值ssthresh=cwnd/2,cwnd=ssthresh+3,转入快速恢复模式
-
快速恢复:报文段守恒
- 每个冗余ACK(说明有一个报文段被端系统接收了),cwnd+=1
- 当发生超时时,修正阈值ssthresh=cwnd/2,cwnd=1MSS,重新慢启动
- 当收到新的ACK时,cwnd=ssthresh,转入拥塞避免模式
-
-