【计算机网络】运输层

计算机网络:自顶向下方法(第五版&第七版)学习笔记,第三章运输层

本章逻辑:概述-三个原理-UDP和TCP原理

概述

  • 运输层为进程提供逻辑通信(logic communication),网络层为主机提供逻辑通信

  • 运输层协议在主机中实现,将进程的报文转化曾报文段(segment)

  • 网络层仅作用于运输层报文段的网络层字段而不检查,接收时网络层提取运输层报文段转交运输层

  • 运输层提供的服务受限于网络层提供的服务(如时延带宽等),但运输层可以提供网络层提供不了的服务(如安全、数据可靠等)

  • 网络层协议IP,尽力而为交付(best-effort delivery service)不保证交付,是不可靠服务(unreliable service)

  • 运输层协议的基本服务

    • 将网络层的传输服务扩展到进程间的传输,这种“扩展”叫多路复用(multiplexing)和多路分解(demultiplexing)
    • 差错检查(error checking)
  • 差错检查是一个端到端原则(end-end principle):这种功能必须基于端到端实现,在较低级别设置这种功能无价值/冗余

  • TCP还提供:可靠数据传输、拥塞控制

多路复用(multiplexing)和多路分解(demultiplexing)

  • 多路分解(demultiplexing):将运输层报文段的数据交付到正确的socket,即检查目的端口号并定向到对应socket
  • 多路复用(multiplexing):从socket中收集数据并封装首部信息生成报文段,并传到网络层
    • socket有唯一标识符(端口号)
    • 报文段有特殊字段指示需要交付到的socket,至少包括源端口号字段(source port number field)、目的端口号字段(destination port number field)
  • 分类为无连接(connectionless)(如UDP)、面向连接(connection-oriented)(如TCP),socket的标识分别为二元组(目的IP、目的端口号)、四元组(源IP,源port,目的IP,目的port)

可靠数据传输(Reliable Data Transfer)

  • 可靠数据传输协议(Reliable Data Transfer Protocol)
  • 用有限状态自动机FSM(finite state machines)说明发送方/接收方
  • (???)ARQ(Automatic Repeat Request,自动重传请求协议)

rdt1.0:完全可靠信道

发送方

接收到数据后,制作package并发送

接收方

接收到数据后,解析并发送给上层

rdt2.0:考虑比特受损

  • 有肯定确认(positive acknowledgement)、否定确认(negative acknowledgement)
  • 又称自动重传请求(Automatic Repeat reQuest)协议,需要差错检测、接收方反馈、重传

发送方

  • 收到上层数据,制作package(包括检验码)并发送
  • 开始等待,若接收到数据并发现是个NAK,重新发送;否则等待上层数据

接收方

接收到数据,如果损坏就发送NAK,否则把数据给上层并发送ACK

rdt2.1、2.2:考虑ACK和NAK损坏

  • 引入分组序号(sequence number),1比特

  • 2.2利用可能出现的冗余(duplicate)ACK代替NAK

  • 发送方:

    • 发送的序号为0或1,因此两个等待上方数据状态有01两种,等待确认信号的状态也有01两种
    • 等待确认时只有不损坏且序号正确才能转换状态去等待上层数据
    • 2.2去掉NAK后,等待确认时要确认是序号对应的ACK
.JPG)
  • 接收方:
    • 接收的序号为0或1,因此两个等待下方接收数据状态有01两种
    • 2.1中如果损坏发回NAK,如果没损坏但序号不对发送上一序号的ACK
    • 上述冗余ACK引出2.2的处理,不管损坏还是序号错,都发送上一序号的ACK
    • 但是不明白为什么2.1发送的是NAK/ACK和checksum,难道不该发01嘛
.JPG)

rdt3.0:考虑比特受损&丢包

  • 引入倒计数定时器(countdown timer)

发送方

  • 发送数据后启动定时器
  • 等待确认时同时响应定时器终止,重新发送包并重启定时器
  • 收到正确的确认后关闭定时器,等待接收上层的下一状态数据
  • 等待上层数据时接收冗余数据分组(可能因为时延被接收方当作ACK丢包并重发),不做处理
.JPG)

接收方(同rdt2.2)

流水线:GBN(回退N步)

  • 上述均为停等协议,对信道(channel)的利用率(utilization)太低,引入流水线传输,不等确认便开始下一个包的发送,需要加序号和缓存(未按序接收的)

  • GBN引入窗口长度限制发送方流水线发送的分组,又称滑动窗口协议(sliding-window protocol)

    • base,基序号,是窗口最前,是最早未确认分组的序号
    • N,窗口长度,整个窗口为[base,base+N1][base,base+N-1],窗口内,要么包没确认,要么没发送
    • nextseqnum,下一个序号,是窗口未发送的包的开始序号,即[base,nextseqnum1][base,nextseqnum-1] 这段都是未确认的,[nextseqnum,base+N1][nextseqnum,base+N-1] 是未发送的

发送方

  • 起始base=nextseqnum=1,发送方仅有一个状态
  • 收到上层的数据包,在窗口未满时不断发送包并更新nextseqnum,窗口满了则向上层拒绝数据(或缓存)
    • 发送包时若是窗口最前端,启动定时器
  • 定时器到期重新发送[base,nextseqnum1][base,nextseqnum-1] 的所有包
  • 收到损坏数据不予理会,收到正确数据窗口移动(根据收到的ACK更新base),如果窗口内已经没有需要发送的包,停止定时器,否则重启定时器,这是一种累积确认(cumulative acknowledgement)

接收方

  • 只按序接收,只维护expectedseqnum
  • 注意区分expectedseqnum和ACK的确认值

流水线:选择重传(SR)

  • Selective Repeat

  • 为解决GBN的大量重传,接收方引入窗口和对应缓存

发送方

  • base改为sendbase,窗口不同处在于[sendbase,nextseqnum1][sendbase,nextseqnum-1] 间可能有已经确认的包
  • 每个分组有自己的逻辑定时器,可用单个硬件定时器模拟多个逻辑定时器
  • 收到ACK后如果在窗口内则标记接收,如果是sendbase则更新sendbase至未确认的最小分组
  • 其他与GBN类似

接收方

  • 维护一个窗口
  • 接收窗口内的失序分组,缓存至前序分组都被收到,一批分组按序交给上层
  • 接收到窗口之前的分组,重新确认那个分组
  • 重新确认的存在表明接受和发送方窗口不一定是一致的,最坏情况是两个窗口完全错开,因此窗口长度序号空间大小/2窗口长度\leq 序号空间大小/2

拥塞控制(Congestion Control)

  • 区分流量控制:拥塞控制侧重网络环境通过控制发送方减轻网络负担,流量控制侧重接收端控制发送方不会overflow对面的缓存
  • 表现:丢包、长时延

三种情况研究拥塞的影响

情况1:2v2,1无穷缓存路由器

  • λin\lambda_{in} 发送速率,λout\lambda_{out} 接收速率,链路容量RR
  • 分组速率接近容量时时延巨大,缓冲区再大也不能解决实质问题

情况2:2v2,1有限缓存路由器

  • λin\lambda_{in} 应用层发送速率,λin\lambda_{in}' 运输层发送速率(包含重传)(又称供给载荷offered load),λout\lambda_{out} 接收速率,链路容量RR

路由器有空间才发送

路由器没空间丢包,仅确认丢包后重发

  • 发送方重传补偿因缓存不足丢失的分组,加重了阻塞
  • λin\lambda_{in}' 增加λout\lambda_{out} 会趋近于R/2R/2

实际:路由器可能重传未丢失分组

  • 大时延带来的不必要重传会使得路由器链路转发不必要的分组副本

情况3:4主机4路由器两跳路径

一个主机(A)的速率增加会导致D到B的吞吐量趋于0

  • 丢包时上游传输的带宽努力都白费了

拥塞控制方法

  • 端到端拥塞控制(end-end):端系统只能观察网络行为得知拥塞(丢包loss、时延delay),无明确显式信息,TCP自行判断与处理

  • 网络辅助(network-assisted)的拥塞控制:路由器向发送方提供显式反馈信息,比如简单就一个比特,或是复杂的指示最大主机发送速率

UDP

  • 用户数据报协议,User Datagram Protocol

报文格式

应用数据:应用层的报文

长度:整个UDP报文段的字节数

原理

  • UDP将从应用得到的数据附上源和目的端口号字段、长度、检验和,并发送给网络层;将网络层得到的数据解析交付给socket
  • 无连接:指UDP发送报文段前没有跟对面运输层握手
  • 差错检验功能:检查传输过程中比特是否变化,但也只能检测,无法恢复
    • 可能因链路中的干扰或者存储路由器时引入问题
    • 所有字(16bit)做循环加法,得到结果取反填入检验和
    • 检验时将所有字加起来,结果应为FFFF(16)FFFF_{(16)}

优点

  • 在应用层更精细(finer)控制数据的发送
  • 无需建立连接,也就不需维护连接状态
  • 分组首部开销小
  • 相比TCP没有拥塞控制、可靠数据传输等功能,时延小

缺点

  • 极端情况下,大量分组溢出,丢包率高,达不到目的地,还会使TCP(因为拥塞机制)减小速率
  • 无可靠通信(但可以在应用程序中实现)

TCP

  • 传输控制协议,Transmission Control Protocol

连接

  • 面向连接的(connection-oriented):发送数据前必须先握手,发送预备报文段(preliminary segment),双方初始化TCP连接相关的状态变量(state variables),总共三次握手(three-way handshake),其中第一次客户发送的报文段没有payload,第三次有
  • 双全工服务(full-duplex service):连接建立后数据可双向流动(flow)
  • 点对点(point-to-point):no multicasting,连接中只有一对主机
  • 可靠、有序、流水线数据传输

报文结构

  • 序号:报文段首字节的字节流编号,字节按MSS(最大报文段长度,Maximum Segment Size)分段
  • 确认号:期望收到的对面的字节流编号,采用累积确认,是否丢弃乱序包由编程人员决定,实践中会保留
  • 接收窗口:简写rcvr window,用于流量控制,指示愿意接受的字节数
  • 注:捎带(piggybacked)确认,比如Telnet中,收到数据时不着急发送ACK,稍等一会若有数据需要发送,将ACK和这个数据一包发走

往返时间(round trip time)和超时

  • 超时时间必须超过RTT,太短会导致不必要的重传,太长会放大丢包的影响
  • SampleRTTSampleRTT:某个报文段发出(交给网络层)到收到ACK的时间,不考虑重传的包,然而会波动
  • 估计RTT:每获得新SampleRTTSampleRTT 就更新,α\alpha 推荐值0.1250.125 ,这是一种指数加权移动平均(exponential weighted moving average)

EstimateRTT=(1α)EstimateRTT+αSampleRTTEstimateRTT=(1-\alpha)\cdot EstimateRTT+\alpha\cdot SampleRTT

  • 偏差RTT:估算SampleRTTSampleRTT 偏离EstimateRTTEstimateRTT 的程度,β\beta 推荐值0.250.25

DevRTT=(1β)DevRTT+βSampleRTTEstimateRTTDevRTT=(1-\beta)\cdot DevRTT + \beta\cdot |SampleRTT-EstimateRTT|

  • 波动大时将估计RTT放大一些作为时间间隔,波动小时缩小一些,每得到新的EstimateRTTEstimateRTT 则更新公式:

TimeoutInterval=EstimatedRTT+4×DevRTTTimeoutInterval = EstimatedRTT + 4\times DevRTT

可靠数据传输

  • 无损坏、无间隙、非冗余、按序
  • 类似SR,但只有一个定时器:
    • 发送数据时没有定时器则开启
    • 重传(只会重传最小未确认报文段)后开启
    • 收到数据后如果还有没确认的报文段则开启,否则关闭
  • 因为累积确认,所以可以直接用ack更新窗口开端(前面的包就算没有ack,对面也一定收到了,不需要考虑重传)
  • 简化版的发送方状态图:
  • 接收方的ACK,其中乱序时可能是冗余ACK也可能是填补了间隔开始部分的普通确认ACK:
flowchart TD
	接收方 -- 收到期望序号 --> 延迟ACK等待下一个期望序号一段时间 -- 超时则确认 --> 发送ACK
	延迟ACK等待下一个期望序号一段时间 --> 收到第二个 -- 立刻确认 --> 发送ACK
	接收方 -- 收到乱序发送期望间隔最小序号的ACK --> 发送ACK
  • 快速重传(fast transmit):超时重发可能时间较长,收到3个冗余ACK就重传(貌似是实践经验,2次更可能是乱序,3次以上更可能丢包)

流量控制(flow control)

  • receiver controls sender, so sender won’t overflow receiver’s buffer by transmitting too much, too fast
  • 接收方维护rwndrwnd 在报文段中指示缓存空间
  • 当没有缓存时发送一个字节的报文段,接收方清空缓存并包含新的rwnd

连接管理

  • 客户请求建立连接,SYN1,随机化选择初始序号
  • 服务器收到后选择自己初始序号,确认序号为客户的序号+1,SYN1,发送SYNACK报文段
  • 客户收到SYNACK后分配缓存和变量,发送报文段(置确认序号为服务器初始序号+1),SYN0,可以加入数据了
  • 为什么不是两次握手?各种延迟(比如传输已经关闭但数据还没到)、重传(传输完成后又建立一个)、乱序
  • 客户打算关闭时发送置FIN1的报文段,服务器收到后回复ACK
  • 服务器打算关闭时发送FIN1的确认报文段,客户收到后回复ACK
  • ACK都收到时两台主机资源释放

客户:

graph
	CLOSED -- 发送SYN尝试建立连接 --> SYN_SENT -- 接受SYNACK发送ACK --> ESTABLISHED -- 发送FIN等待关闭连接 --> FIN_WAIT_1 -- 接收ACK -->  FIN_WAIT_2 -- 接收FIN回复ACK --> TIME_WAIT -- 等待30s --> CLOSED

服务器:

graph
	CLOSED -- 套接字监听 --> LISTEN -- 接受SYN发送SYNACK --> SYN_RCVD -- 接收ACK --> ESTABLISHED -- 接收FIN发送ACK --> CLOSE_WAIT -- 发送FIN --> LAST_ACK -- 接收ACK --> CLOSED

拥塞控制

  • receiver controls sender, so sender won’t overflow receiver’s buffer by transmitting too much, too fast

  • 性质:加性增,乘性减,AIMD,Additive Increase Multiplicative Decrease,当TCP发送方感受到端到端路径无拥塞时就线性的增加其发送速度,当察觉到路径拥塞时就乘性减小其发送速度

  • cwndcwnd :发送方维护的拥塞窗口长度

  • ssthreshssthresh:慢启动阈值

  • 发送速率ratecwndRTT(bytes/sec)rate\approx\frac{cwnd}{RTT}(bytes/sec)

慢启动(Slow Start)

  • 超时:cwnd=1MSS,ssthresh=cwnd/2cwnd=1MSS,ssthresh=cwnd/2 ,重传分组,进入慢启动状态

  • ACK冗余33ssthresh=cwnd/2,cwnd=ssthresh+3MSSssthresh=cwnd/2,cwnd=ssthresh+3MSS ,进入快速恢复状态

慢启动状态

  • 初始cwnd=1MSScwnd=1MSS,每确认一个报文段cwnd+=1MSScwnd+=1MSS ,即以指数增长
  • 超过ssthreshssthresh:进入拥塞避免状态

快速恢复状态

  • 冗余ACK:cwnd+=1MSScwnd+=1MSS
  • 得到新的ACK:cwnd=ssthreshcwnd=ssthresh

拥塞避免

得到新的ACK:cwnd+=MSS/cwndMSScwnd+=MSS/cwnd\cdot MSS

TCP Tahoe & TCP Reno

上面给的是Reno,Tahoe不管是超时还是3个冗余都是恢复到慢启动开始指数增长,到阈值线性增长

宏观吞吐量(throughput)

窗口长度w

TCPthruputave=34WRTT(bytes/sec)TCPthruput_{ave} = \frac{3}{4}\frac{W}{RTT}(bytes/sec)

高带宽路径的平均吞吐量

TCPthruputave=1.22×MSSRTTL(bytes/sec)TCPthruput_{ave} = \frac{1.22\times MSS}{RTT\sqrt{L}}(bytes/sec)

公平性

吞吐量和应等于RR ,指数增长会使得和超过R(直线沿45°走),引起丢包,减小窗口,和减少(直线沿丢包的那个点与远点的连线走)