传输层

传输层
概述
端到端通信
主要协议
UDP
TCP
协议端口
服务器端使用的端口
0~45151
熟知端口号(全球通用端口号)
- 1~1023
登记端口号
- 1024~49151
客户端使用的端口
- 45152~65535
PDU
TCP报文段
UDP用户数据报
作用
- 为应用进程之间提供端到端的逻辑通信
重要功能
- 分用与复用
UDP
特点
无连接、不可靠
尽最大努力交付
面向报文
- 发送方的UDP对应用程序交下来的报文,在添加首部后就向下交付IP层
没有拥塞控制
支持一对一、一对多、多对一、多对多等交互通信
首部开销小,只有8字节
UDP的首部格式
- 子主题 1
TCP概述
特点
面向连接
- 建立逻辑连接
点对点通信
可靠交付
全双工通信
有拥塞控制
基于字节流
没有固定的报文边界
接收端读取recv时,不对数据量做任何假设
应用记录边界标识
用特殊的结束符
给报文加上首部,记录报文长度
TCP的连接
连接的端点称为套接字(Socket)或插口
TCP连接::={socket1,socket2} = {(IP1:port1),(IP2:port2)}
报文首部格式
固定首部
源端口和目的端口(2+2字节)
序号(4字节)
- 本报文段发送数据的第一个字节的序号
确认号(4字节)
- 期望收到对方下一个报文段的第一个数据字节的序号
数据偏移(即首部长度)(4位)
保留(6位)
- 保留使用,目前置为0
紧急URG(URGent)
当URG=1,表明紧急指针字段有效。
发送方
确认ACK(ACKnowledgment)
- 当ACK=1,确认号有效;当ACK=0,确认号无效
推送PSH(PuSH)
- 接收TCP收到PSH=1的报文段,就尽快交付接收应用进程,而不再等到整个缓存都填满后再向上交付
复位RST(ReSeT)
- 当RST=1,表明TCP连接中出现严重差错,需释放连接,重新建立运输连接
同步SYN(SYNchronization)
SYN=1,ACK=0:连接请求报文段
SYN=1,ACK=1:连接接受报文段
终止FIN(FINish)
用来释放一个连接
FIN=1表明此报文段的发送端的数据已发送完毕,并要求释放运输连接
窗口(2字节)
校验和(2字节)
- 检验范围:首部+数据
紧急指针(2字节)
- 在URG=1时,指出本报文段中的紧急数据的字节数(紧急数据结束后就是普通数据),指出紧急数据的末尾在报文段中的位置
选项(最长40字节)
使TCP首部长度是4字节的整数倍
最大报文短长度MSS(Maximum Segment Size)
每个TCP报文段中的数据字段的最大长度
与接收窗口值没有关系
默认值:536字节
窗口扩大(3字节)
其中一个字节表示移位值S
窗口值位数从16增大到(16+S)位
移位值S允许使用的最大值是14
窗口最大值增大到
选择确认
*可选部分(4n字节)
可靠传输
工作原理
停止等待协议(stop and wait)
无差错情况
- A发送一个分组,B收到后发送确认,A收到确认后发送下一个分组
有差错情况
A发送一个分组,B检测到出错,不发送确认,A持续等待
超时重传
- A发送消息完毕后,超过一定时间没有收到确认,重传前面发过的分组
确认丢失和确认迟到
A在超时计时器到期后重传M
假定B又收到了M
丢弃新的M分组
向A发送确认
要点
停止等待
- 每发送完一个分组就停止发送,等待对方的确认。收到确认后再发哦是哪个下一个分组
编号
- 对分组进行编号
暂存
- 发送方缓存出错的分组
超时 重传
- 超过一定等待时间后,发送方重新发送分组
超时计时器的重传时间应当比数据再分组传输的平均往返时间更长一些,防止没必要的重传
简单,但信道利用率低
流水线传输
在收到确认前,连续发送多个分组
目的:提高信道利用率
连续ARQ(自动重传请求)协议
发送窗口
- 位于窗口内的分组都可连续发送出去,而不需要等待对方的确认
滑动窗口
- 每收到一个确认,把发送窗口向前滑动一个分组位置
累积确认
- 接收方对按序到达的最后一个分组发送确认
Go-back-N
表示需要再退回来重传已发送过的N个分组
缺点:通信质量不好时,重传大量不必要分组
TCP可靠传输的实现
滑动窗口
发送窗口
接收窗口
以字节为单位
超时重传
加权平均往返时间RTTs
超时重传时间RTO
应略大于RTTs
RFC 6298建议
RTTD
- RTT的偏差的加权平均值,与RTTs和心得RTT样本之差有关
Karn算法
情景
- 发送报文段,超时未收到确认,重传报文段,收到确认,无法判断是对原报文段还是重传报文段的确认
目的
- 使得出的加权平均RTTs和RTO较准确
思路
- 在计算加权平均RTTs时,只要报文段重传了,就不采用其往返时间样本
问题
- 若报文段时间突然增大,超时重传时延RTO无法更新
修正的Karn算法
报文段每重传一次,就把RTO增大一些
- 典型做法:新RTO=2旧RTO
当不再发生重传时,才正常计算RTO
选择确认SACK
作用:只传送缺少的数据,而不重传已经正确到达的数据
用法:双方建立TCP连接时,在TCP首部选项中加上“允许SACK”的选项
1字节指明是SACK选项,1字节指明这个选项要占多少字节
指明一个字节块用掉8字节(序号有32位,需用4字节表示)
最多指明4个字节块(首部选项最大长度40字节)
TCP流量控制
滑动窗口
原理
- 发送方根据接收方通告的接收窗口动态调整发送数据量
死锁问题
接收方发送零窗口通知,发送方停止发送
接收方发送的非零窗口通知丢失
发送方一直等待接收方的非零窗口通知
接收方一直等待发送方发送数据
解决方法:持续计时器
持续计时器
只要TCP连接的一方收到对方的零窗口通知,就启动持续计时器
持续计时器到期,就发送一个零窗口探测报文段(仅携带1字节的数据)
对方在确认这个探测报文段时给出现在的窗口值
- 仍为0,重新设置持续计时器
传输效率
用不同机制控制TCP报文段的发送时机
机制一
TCP维持一个变量,等于最大报文段长度MSS
只要缓存中的数据打到MSS字节时,就组装成一个TCP报文段发送出去
机制二
- 由发送方的应用进程指明要求发送报文段,即TCP支持的推送(push)操作
机制三
- 发送方的一个计时器到期后,把当前缓存数据装入报文段(不能大于MSS)发送出去
糊涂窗口综合征
现象
- 交换的报文段中的数据部分过小,消耗的资源多,传输效率小
发送方
原因
- 接受到来自应用程序的数据时马上发送数据
解决方式:Nagle算法
若应用程序逐字节发送数据,则发送第一个数据字节,缓存后续数据字节
收到对第一个数据字节的确认后,发送缓存,同时缓存后续数据
接收方
原因
- 接收方应用进程消耗数据太慢,拥塞控制窗口过小
解决方式:让接收方等待一段时间
等到接收缓存已有足够空间容纳一个最长的报文段
或者等到接收缓存已有一半空闲的空间
TCP拥塞控制
原理
拥塞的概念
- 某段时间,若对网络中某资源的需求超过了该资源所能提供的可用部分,网络性能就要变坏
拥塞的原因
链路容量不足、资源分配不均衡
路由器缓存空间、流量分布不均衡
处理机速度太慢
开环控制方法
- 在设计网络时考虑发生拥塞的因素,力求网络不产生拥塞
闭环控制方法
基于反馈环路的概念
检测:检测网络系统以便检测到拥塞在何时、何处发生
传送:将拥塞发生的信息传送到可采取行动的地方
调整:调整网络系统的运行以解决出现的问题
方法
基于窗口(属于闭环控制)
发送方维持一个拥塞窗口CWND(Congestion Window)
拥塞窗口的大小取决于网络的拥塞程度,并动态变化
发送方让自己的发送窗口等于拥塞窗口
拥塞判断依据
超时重传计时器超时
- 网络已经出现了拥塞
收到3个重复的确认(ACK)
- 预示网络可能会出现拥塞
算法
慢开始
目的
- 探测网络的负载能力或拥塞程度
思路
- 由小到大逐渐增大注入到网络中的数据字节,即:由小到大逐渐增大拥塞窗口数值
算法
- 每收到一个对新的报文段的确认后,把拥塞窗口增加最多一个SMSS的数值
轮次与门限值
慢开始门限ssthresh
cwnd < ssthresh
- 使用慢开始算法
cwnd > ssthresh
- 停止使用慢开始算法,改用拥塞避免算法
cwnd = ssthresh
- 既可以使用慢开始算法,也可以使用拥塞避免算法
传输轮次
- 把拥塞穿孔cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认
发送方判断网络出现拥塞时(超时重传计时器超时)
慢开始门限ssthresh = max (cwnd/2 , 2)
拥塞窗口cwnd = 1
执行慢开始算法
拥塞避免
目的
- 让拥塞窗口cwnd缓慢地增大,避免出现拥塞
思路
每经过一个传输轮次,拥塞窗口cwnd = cwnd +1
让拥塞窗口按线性规律缓慢增长
快重传与快恢复FR
快重传
目的
- 让发送方尽早知道发生了个别报文段的丢失
算法
发送方 只要连续收到三个重复的确认,就立即进行重传(不用等到超时计时器超时)
要求接收方立即发送确认,即便是收到了失序的报文段
快恢复
发送端收到连续三个重复的确认时,不执行慢开始算法,而是执行快恢复FR算法
算法
慢开始门限ssthresh = 当前拥塞窗口cwnd/2
新拥塞窗口cwnd = 慢开始门限ssthresh
开始执行拥塞避免算法,使拥塞窗口缓慢地线性增大
小结
- 发送方窗口的上限值 = Min(接收窗口rwnd,拥塞窗口cwnd)
*主动队列管理AQM(Active Queue Management)
路由器分组丢弃策略
先进先出策略
- 先到的分组先处理
尾部丢弃策略
- 处理队列满后,丢弃后续分组
严重问题:全局同步
- 子主题 1
主动
不要等到路由器的队列长度已经达到最大值时才不得不丢弃后面到达的分组
在队列长度达到某个值得警惕的数值时(有拥塞征兆),就主动丢弃到达的分组
实现方法
随机早期检测RED
- 经过多年实践证明,RED算法效果不太理想
TCP连接管理
三次握手
握手
- TCP建立连接的过程
二报文握手建立连接的问题
客户第一次握手报文迟到,服务器发送确认报文,建立连接
服务器等待客户发送数据,而客户并没有数据要发送
为什么要三次握手
- 客户和服务器之间交换三个TCP报文段,以防止已失效的连接请求报文段突然又传送到了,因而产生TCP连接建立错误
流程
第一次握手
A发送连接请求报文
SYN = 1
seq = x
不携带数据,但消耗一个序号
第二次握手
B收到请求报文段,如同意,发送确认
SYN = 1
ACK = 1
ack = x + 1
seq = y
不携带数据,但消耗一个序号
第三次握手
A收到同意报文,向B给出确认
ACK = 1
ack = y + 1
seq = x + 1
A的TCP通知上层应用进程,连接已经建立
四次挥手
流程
第一次挥手
A的应用进程先向其TCP发出连接释放报文段,并停止再发送数据,主动关闭TCP连接,等待B的确认
FIN = 1
seq = u
TCP规定:FIN报文即使不携带数据,也消耗掉一个序号
第二次挥手
B发出确认
ACK = 1
ack = u +1
seq = v
TCP服务器通知高层应用进程
TCP连接处于半关闭(half-close)状态
从A到B这个方向的连接释放掉了
B若发送数据,A仍要接受
第三次挥手
若B已经没有要向A发送的数据,其应用进程就通知TCP释放连接
FIN = 1
ACK = 1
ack = u +1
seq = w
第四次挥手
A收到连接释放报文段后,必须发出确认
ACK = 1
ack = w + 1
seq = u + 1
B收到确认后,释放TCP连接
A等待2MSL的时间,后才释放TCP连接
保证发送的最后一个ACK报文段能够到达B
防止“已失效的连接请求报文段”出现在本连接中
保活计时器
作用
- 防止TCP连接出现长时期的空闲
流程
通常设置为2小时
若服务器超过2小时还没收到客户的信息,就发送探测报文段
若发送了10个探测报文段还没有响应,就假定客户出了故障,因而就终止该连接
小结:TCP四个计时器
超时重传计时器
坚持计时器(0窗口报文探测计时器)
时间等待计时器(2MSL关闭连接)
保活计时器