1 概述和传输层服务
- 传输层服务:进程之间的逻辑通信
- 依赖网络层的服务(延时、带宽)
- 对网络层的服务进行加强(数据丢失、顺序混乱、加密)
- TCP:多路复用解复用、建立连接、拥塞控制、流量控制
- UDP:多路复用解复用
- TCP和UDP都不提供延时和带宽保证
- 网络层服务:主机之间的逻辑通信
2 多路复用与解复用
- TCP多路解复用(通过四元组区分socket)
- 主机收到IP数据报,每个数据报有源IP端口和目标IP端口
- 每个数据报承载一个传输层报文段
- 主机根据IP和端口号将报文段发送给对应的socket套接字
- UDP多路解复用(通过二元组区分socket)
- 主机收到UDP报文段,检查报文段目标端口号
- 根据端口号定位对应的socket套接字
3 无连接传输:UDP
UDP:用户数据报协议,是无连接的,每次以报文为单位发送,仅仅在网络层基础上增加了端口。头部只有8个字节(64bit),包括源端口号、目标端口号、长度、校验和
4 可靠数据传输原理
4.1 RDT渐进式开发
渐进式的开发可靠数据传输协议(rdt)的发送方和接收方,使用有限状态机(FSM)来描述发送方和接收方
4.1.1 Rdt 1.0
假设在可靠信道上的可靠数据传输
- 下层的信道是完全可靠的
- 没有比特出错、没有分组丢失
- 发送方和接收方的FSM
- 发送方将数据发送到下层信道
- 接收方从下层信道接收数据
4.1.2 Rdt 2.0
下层信道可能会出错,出现比特翻转,应该设计具有比特容差的信道
- 确认(ACK):接收方显示告诉发送方分组已经正确接收
- 否定(NAK):接收方显示告诉发送方分组发生了差错
- 发送方接收到NAK后重传分组
4.1.3 Rdt 2.1
ACK和NAK也可能出错,导致发送方不知道应该做什么,通过引入序号的机制可以解决该问题
- 停止等待协议
- 发送方在每个分组中加入序号
- 如果ACK/NAK出错,发送方重传当前分组
- 接收方收到重复的分组,重新发送ACK/NAK,并将该分组丢弃(不发给上层)
4.1.4 Rdt 2.2
无NAK的协议,与Rdt2.1功能相同,但是只是用ACK就可以解决所有问题
- 接收方对最后正确接收的分组发ACK
- 收到重复的ACK(如ACK0)时,发送方与收到NAK采取相同的动作:重传当前分组
- 为后面的一次性发送多个数据单位做准备
4.1.5 Rdt 3.0
具有比特差错和分组丢失的信道,解决下层通道可能丢失分组的问题,否则一直等待ack导致程序死锁
- 发送端超时重传
- 重传会导致数据重复,但rdt2.2序号已经解决了该问题
- 接收方指明被正确接收的序列号
rdt3.0性能存在问题,每次传一个分组,然后等待回复后再传输一个分组,这期间链路都是空闲的,用形象的例子就是高速公路上每次只能有一辆车从一个地方开到另一个地方,然后再开回来。
4.2 流水线协议
- 流水线:允许发送方未得到确认的情况下发送多个分组
- 增加序号的范围:用多个bit描述分组的序号
- 在发送方/接收方都需要有缓冲区
- 发送方缓冲:未得到确认,可能需要重传
- 接收方缓冲:上层用户取数据的速率 ≠ 接收到的数据速率,接收到的数据可能乱序,需要排序后交付
4.2.1 滑动窗口协议
- 发送缓冲区
- 形式:内存中一个区域,落入缓冲区的分组可以发送
- 功能:用于存放已发送,但是没有得到确认的分组
- 必要性:需要重发时可用
- 发送缓冲区的大小:一次最多发送多少未经确认的分组
- 停止等待协议 = 1 (GBN)
- 流水线协议 > 1,但链路利用率不能超100%(SR)
- 发送缓冲区中的分组
- 未发送的:落入缓冲区的分组,可以连续发送出去
- 已发送但等待确认的分组:发送缓冲区的分组只有得到确认才能删除
滑动窗口协议-发送窗口:绿色部分是滑动窗口,表示了落入缓冲区的分组,可以发送;前沿和后沿指针中间表示了发送窗口,是已经发送但没有确认的部分。当0号得到确认后,后沿可以移动到1号位置,滑动窗口也向前滑动。
滑动窗口协议-接受窗口:绿色部分是滑动窗口,表示可以接收的分组数量;如果接收到1、2分组但未接收到0号分组,滑动窗口不会向前滑动,当接收到0号分组后,会一次滑动3个序号的长度。
4.2.2 GBN和SR
- GBN和SR都是发送窗口>1,且未经确认可以发送多个分组
- 回退N步(Go-back-N):一个包丢失会导致整个窗口重传
- 接收窗口大小=1
- 接收端只能顺序接收
- 发送端发送了012345,一旦1没有发送成功,就必须完全重新传输12345
- 简单、所需资源少,但出错后回退N步代价大
- 选择性重传(Selective Repeat)
- 接收窗口大小>1
- 接收端可以乱序接收
- 发送端可以根据接收端的信息选择性重传
- 复杂、所需资源多,但出错后只需重传一个分组
5 面向连接的传输:TCP
- 点对点:一个发送方,一个接收方
- 可靠地、按顺序的字节流,无报文边界
- 管道话(流水线):TCP拥塞控制和流量控制、设置窗口大小
- 发送和接收缓存
- 全双工数据
- 同一连接中数据双向流动
- MSS:最大报文段大小
- 面向连接:在数据交换之前,通过握手初始化发送方和接收方的状态变量
- 有流量控制:发送方不会淹没接收方
5.1 TCP报文结构
- seq 序号:该包的序列号。TCP报文段body部分(应用层数据)首字节在字节流的编号,TCP协议根据seq来确定顺序
- ack 确认号:该包的确认号(累计确认)。表示对对方已经收到了多少字节流,期望从另一方收到的下一个字节的序号。
- 下面是TCP seq 序号的一个例子,该包的第一个包数据段 seq=1,该包的body部分长度未1448,该包的下一个序号就是 1+1448,以此类推,seq和ack都是字节流为单位的编号
5.2 超时重传
TCP往返延时(RTT)和超时:超时重传设置的时间与采样往返延时挂钩,TCP维持一个均值采样RTT,公式如下
EstimatedRTT = (1-α) * EstimatedRTT + α * SampleRTT ( α推荐值是α=0.125)
除了估算RTT外,测量RTT的变化也是有价值的,以下用于估算SampleRTT一般会偏离EstimatedRTT的程度:
DevRTT = (1-β) * DevRTT + β * |SampleRTT - EstimatedRTT|
最后超时重传的时间通过下面公式计算,因为设置为均值RTT是没有价值的,但是也不应该比均值RTT大太多
TimeoutInterval = EstimatedRTT + 4 * DevRTT
TCP设置的累计确认是类似于GBN的,ACK表示该序号以及该序号之前的字节流都完成了接收工作
两种情况会触发重传事件,重传机制类似于SR
- 超时(只重发最早的未确认段:SR)
- 快速重传(收到ACK50后连续收到3个ACK50,重传序号最小的段ACK50)
5.3 流量控制
接收方控制发送方,不让发送方发送过快导致接收方的缓冲区溢出
- 接收方反馈给发送方的TCP报文头部rwnd字段“通告”其空闲buffer大小
- RcvBuffer大小通过socket选项设置,默认为4096字节
- 很多操作系统自动调整RcvBuffer
- 发送方限制未确认字节的个数≤发送方过来的rwnd值
- 保证接收方不会淹没发送方
5.4 连接管理
- 正式交换数据前,发送方和接收方握手建立通信关系
- 同意建立连接
- 初始化连接参数
- 两次握手存在的问题
- 客户端:发起连接请求
- 连接请求在网络中存在延时,导致客户端超时重发
- 服务器:收到了第一次延时到达的请求,返回给客户端同意连接
- 客户端:收到错误的同意连接,因为这个连接信息对应的是第一次延时的段
- 服务器:会维护虚假的半连接,客户端已经放弃这个连接了,服务器仍然在维护
- 三次握手(本质上是客户端给服务器一个序号,服务器返回客户端一个序号,两方都确认收到该序号,最少需要3次)
- 客户端:选择初始化序号,发送TCP SYN报文,Seq=X
- 服务器:返回SYNACK报文,Seq=Y,ACK=X+1
- 客户端:发送SYNACK报文(可能包含数据),ACK=Y+1
- 关闭连接(不太完美,用定时器在一段时间后如果还没收到就当他释放了)
- 客户端:申请连接拆除
- 服务器:同意拆除连接(拆除客户端 -> 服务器方向的连接)
- 服务器:申请连接拆除
- 客户端:同意拆除连接(拆除服务器 -> 客户端方向的连接)
5.5 拥塞控制
- 端到端的拥塞控制(TCP采用的方法)
- 没有来自网络层的显示反馈:路由器负担较轻、符合网络核心简单的原则
- 端系统根据延时和丢失事件判断是否拥塞
- 网络辅助的拥塞控制
- 路由器提供给端系统反馈信息
- 单bit置为显示有用色(SNA,DECbit,TCP/IP ECN,ATM)
- 显示提供发送端可以采用的速率
5.5.1 TCP拥塞感知
某个段超时了(丢失事件):
拥塞
- 网络拥塞(某个缓冲区没有空间了,被丢弃)概率大
- 出错被丢失(各级错误,没有通过校验,被丢失)概率小
- 有可能出现误判,但整体控制方向是对的
有关某个段的3次重复ACK:
轻微拥塞
- 网络这时还能够进行一定程度的传输,拥塞但情况要比第一种好
5.5.2 TCP拥塞控制
- 通过维持 CongWin 拥塞窗口的值来控制发送端的发送速度
- SS阶段:加倍增加(每个RTT)
- CA阶段:线性增加(每个RTT)
- 超时或3个重复ack需要降低拥塞窗口的值
- 超时:CongWin降为1MSS,进入SS阶段再倍增到ConWin/2(每个RTT),从而进入CA阶段
- 3个重复ACK:CongWin降为CongWin/2,CA阶段
- 联合控制(发送速率由下面两个联合控制)
- 缓冲区剩余大小
- 拥塞窗口大小
- TCP慢启动:
- 连接开始时,CongWin=1MSS(例如MSS=1460bytes,RTT=200s,初始速率为58.4kbps)
- 连接开始后,指数性增加速率,每个RTT CongWin加倍
- 1 -> 2 -> 4 -> 8 -> 16 -> 32 -> 64 -> 128 …
- TCP拥塞控制:Additive Increase Multiplicative Decrease(AIMD, 乘性减,加性增)
- 乘性减:超时:丢失事件后将CongWin将为1,将CongWin/2作为阈值,进入慢启动SS阶段
- 加性增:当CongWin>阈值后,每个RTT将CongWin加1MSS
- 3个重复ACK:直接进入加性增CA阶段
- 整体的吞吐量大约为 3/4 最大吞吐量
TCP公平性
- 假设有两个设备,并且两个设备的RTT相同
- 设备A和设备B的带宽和为R
- 假设开始时B的速率比A的速率快,大家都处于拥塞避免的阶段,则A和B的和会向右上移动
- 发生拥塞后,A和B的速率都降低到原来的 1/2 ,此时A’和B’相当于橙色连线中点处的值
- 不断循环该过程,A和B的速率会趋向于相同