运输层
文章目录
3.1 运输层服务
一,运输层和网络层的比较
运输层为相互通信的应用进程提供了逻辑通信
运输层: 进程间的逻辑通信
网络层: 主机间的逻辑通信
二,运输层协议数据的封装
通常链路层最大传输单元,为1500个字节
TCP具有最大报文长度(MaximumSegment Size,MSS),需减去ip请求头,20个bit,减去20个TCP报头,就是报文长度最大为1460
二,因特网运输层协议
可靠的、按序的交付(TCP)
- 拥塞控制
- 流量控制
- 连接建立
不可靠、不按序交付(UDP)
- “尽力而为”IP协议基础上 不提供不必要服务的扩展
它们都是不保证时延和带宽,具体在业务层保证
3.2 复用与分解
多路复用与多路分解将由网络层提供的主机到主机的交付服务延伸到进程到进程的交付服务
分解:将运输层接收到的报文段交付给正确的套接字(一路到多路,向上)
复用:从多个套接字收集数据,用首部封装数据(多路到一路,向下)
无连接的复用和分解
UDP套接字由二元组标识:
- 目标ip
- 目标端口
思考:
假定在主机C上的一个进程有一个具有端口号6789的UDP套接字。假定主机A和主机B都用目的端口号6789向主机C发送一个UDP报文段。这两台主机的这些报文段在主机C都被描述为相同的套接字吗?如果是这样的话,在主机C的该进程将怎样知道源于两台不同主机的这两个报文段?
答:是的,两个报文段都将指向同一个套接字。UDP套接字由二元组标识。对于每个接收到的报文段,操作系统都将向进程提供其源IP地址,通过所收到的IP数据报可以确定各个报文段的起源
面向连接分解
TCP套接字由四元组标识:
- 源IP地址
- 源端口号
- 目的IP地址
- 目的端口号
思考:假定在主机C端口80上运行的一个Web服务器。假定这个Web服务器使用持续连接,并且正在接收来自两台不同主机A和B的请求。被发送的所有请求都通过位于主机C的相同套接字吗?如果它们通过不同的套接字传递,这两个套接字都具有端口80吗?讨论和解释之
答:对于每个持久连接,Web服务器都会创建一个单独的“连接套接字”。每个连接套接字由一个四元组标识:(源IP地址、源端口号、目标IP地址、目标端口号)。当主机C接收到IP数据报时,它会检查数据报中的这四个字段,以确定它应该将TCP报文段的有效负载传递到哪个套接字。因此,来自A和B的请求通过不同的套接字。A和B的请求会通过80端口找到Web服务器进程, 就这里而言它们通过C的欢迎套接字进行三次握手连接, 这个欢迎套接字具有端口80.当它们与服务器进程建立连接的时候,服务器进程会单独为它们分配套接字, 通过专门的“连接套接字”响应客户端的请求. 这两个套接字就不具有80端口了
多线程Web服务器
当今高性能Web服务器通常只使用一个进程,但为每个新的客户连接创建一个具有新连接套接字的新线程
3.3 无连接传输: UDP
UDP协议特点
-
无连接创建(它将增加时延)
-
简单:在发送方、接收方无连接状态
-
段首部小
-
无拥塞控制: UDP能够尽可能快地传输
-
丢包
-
对应用程序交互失序
应用:
- DNS
- 路由表更新
- SNMP(简单网络管理协议)
要想有可靠性,必须在应用层增加
UDP检验和
将报文所有内容分隔为16比特整数序列,初始UDP校验和位置全为0,然后全部相加后,取反,即为UDP校验和
当数字作加法时,最高位进比特位的进位需要加到结果中
思考:UDP提供的是端到端的差错检测,链路层对传输过程的帧进行差错检查。因此UDP提供的差错检查是否没有必要?
我没搞懂
3.4 可靠数据传输的原则
不可靠信道的特点决定了可靠数据传输协议(rdt) 的复杂性
我们逐渐递增地研究可靠数据传输协议(rdt) 的发送方和接收方
###rdt1
底层信道非常可靠:无比特差错且分组按序无丢失
发送方:
接收方:
但是完美的信道不存在
###rdt2
具有比特差错的底层信道:有比特差错,但分组按序无丢失
与rdt1相比,增加了检错,反馈(ACK为正确收到,NAK为错误收到),重传的机制
它是一个停等协议:发送方发出1个分组,等待 接收方响应后再继续发送
发送方:
接收方:
rdt2有重大缺陷,如果ACK/NAK受损,接收方不清楚将是什么情况,如果重传的话,会导致重复,因此我们需要对每个分组增加序列号,也就是进化成rdt2.1
rdt2.1
发送方,处理受损的ACK/NAK
接收方,处理受损的ACK/NAK
注意:rdt2.1的发送方状态增加了一倍,状态必须“记住”是否 “当前的”分组具有0或1 序号;接收方必须检查是否接收到的分组是冗余的
问题1:两个序号seq. #’ s (0,1) 将够用. ( 为什么?)
因为是停等协议
问题2:必须检查是否收到的ACK/NAK受损?
必须检查,这样才知道发送的包是否成功接收
rdt2.2
这是一个无NAK的协议,只需要在ACK里面带有分组的序号,如果需要不正确,重传即可
###rdt3
能够处理具有差错和丢包的信道
方法:发送方等待ACK一段“合理的”时间,如果没有等待到就重传,简单来说就是加一个定时器
发送方:
rd3效率很低,网络资源利用率很低,由于停等协议
但是停等协议如果不存在的话,发送方网络和接收方的网络能够对报文重排,那么比特交替协议将不能正确工作,将会乱序
流水线协议
发送方允许发送多个、“传输中的”,还没有应答的报文段
它比较停等协议能增加利用率
滑动窗口协议
发送方和接收方都具有一定容量的缓冲区(即窗口),允许发送站连续发送多个分组而不需要等待应答
发送窗口:发送端允许连续发送的分组的序号表
接收窗口:接收方允许接收的分组的序号表
Go-Back_N
发送窗口尺寸为N;接收窗口尺寸为1;位于发送窗口内的分组才允许被发送,位于接收窗口内的分组才能被接收,关键是窗口如何滑动
重要特征:累计ACK(对正确接收的分组总是发送具有最高按序序号的ACK),全部重传
发送方FSM:
- 发送窗口滑动的条件:收到1个确认分组
- 超时重传时,重传所有未被确认的分组
接收端FSM:
- 接收窗口滑动的条件:收到期望序号的分组
- 累计ACK(n):表明已经正确收到序号n(包括n)以前的分组
- 对失序分组的处理:丢弃,重发(已按序接收分组的)ACK
例子:
缺点:有不必要的重传问题
选择重传
发送窗口尺寸为N;接收窗口尺寸为N;
特征:独立ACK,重传单个分组
-
独立ACK: 对每个分组使用单独的确认
-
需N个定时器,若某个分组超时,则重传该分组
-
接收窗口为N,对非按序到达的分组进行缓存
发送方:
- 发送窗口滑动的条件:收到最低位置分组的确认
- 超时重传时,仅重传超时的单个分组
接收方:
- 接收窗口滑动的条件:收到最低位置的分组
- 单独ACK
- 对失序分组的处理:接收窗口内缓存,发对应ACK;接收窗口外丢弃
例子:
问题:当接受窗口太大,难以区分新分组和重传分组,因此窗口长度需要小于等于序号空间的一半
可靠传输的机制:
机制 | 用途和说明 |
---|---|
检验和 | 用于检测在一个传输分组中的比特错误 |
定时器 | 用于检测超时/重传一个分组,可能因为该分组(或其ACK)在信道中丢失了。由于当一个分组被时延但未丢失(过早超时),或当一个分组已被接收方收到但从接收方到发送方的ACK丢失时,可能产生超时事件,所以接收方可能会收到一个分组的多个冗余拷贝 |
序号 | 用于为从发送方流向接收方的数据分组按顺序编号。所接收分组的序号间的空隙可使该接收方检测出丢失的分组。具有相同序号的分组可使接收方检测出一个分组的冗余拷贝 |
确认 | 接收方用于告诉发送方一个分组或一组分组已被正确地接收到了。确认报文通常携带着被确认的分组或多个分组的序号。确认可以是逐个的或累积的,这取决于协议 |
否定确认 | 接收方用于告诉发送方某个分组未被正确地接收。否定确认报文通常携带着未被正确接收的分组的序号 |
窗口、流水线 | 发送方也许被限制仅发送那些序号落在一个指定范围内的分组。通过允许一次发送多个分组但未被确认,发送方的利用率可在停等操作模式的基础上得到增加。我们很快将会看到,窗口长度可根据接收方接收和缓存报文的能力或网络中的拥塞程度,或两者情况来进行设置 |
3.5 面向连接的传输: TCP
- 端到端:连接状态不为路由器所知,从发送方到接收方
- 可靠有序,具有缓冲区
- 面向连接,双向数据流
- 能够流量和拥塞控制
报文段结构
TCP序号就是已经发送第一个字节序号,确认号就是期待对方发送的下一个字节序号
为什么不从0开始编号呢?
为了防止预测攻击
尽可能的避免数据混淆(如果cs断开后,会有可能某些数据仍然滞留在网络中。当cs再次连接,这些延迟数据在建立新连接之后才到达Server,如果都是从0开始会使得新连接与旧连接数据包重叠几率大大增加,造成数据混淆)
如何设置超时的时间?
理论上,超时的时间最好是一个RTT的值,但是取每次的RTT值是非常不好的,变化大,为了”较平滑“,取m平均最近的测量值,并不仅仅是当前SampleRTT
EstimatedRTT = (1- α )*EstimatedRTT + α*SampleRTT
α通常为1/8这样,RTT的预计值就出来了,但是超时的时间,最好有个容量,不能太大也不能太小,叫它安全余量
DevRTT = (1-β)*DevRTT + β|SampleRTT-EstimatedRTT|*
β通常为1/4,然后超时值就为
TimeoutInterval = EstimatedRTT + 4*DevRTT
###可靠数据传输
TCP在IP不可靠服务的基础上创建可靠数据传输服务
- 从应用层接收数据
- 创建报文段
- 启动计时器
- 超时
- 重传
- 重启计时器
- 收到确认(累计确认)
- 更新SendBase
- 如果还有没有传递的报文段,重新启动计时器
NextSeqNum = InitialSeqNum
SendBase = InitialSeqNum
loop (forever) {
switch(event)
event: data received from application above
create TCP segment with sequence number NextSeqNum
if (timer currently not running)
start timer
pass segment to IP
NextSeqNum = NextSeqNum + length(data)
event: timer timeout
retransmit not-yet-acknowledged segment with
smallest sequence number
start timer
event: ACK received, with ACK field value of y
if (y > SendBase) { /* 累计确认到y */
SendBase = y
if (there are currently not-yet-acknowledged segments)
start timer
}
} /* end of loop forever */
由于重传的情况很多,重传的话时间间隔长,所以出现了快速重传(在定时器超时之前重传)的算法,这也是TCP实现可靠数据传输有特点的地方
通过冗余ACK,检测丢失的报文段,然后重传
//事件: 收到ACK, ACK 域的值为 y
if (y > SendBase) {
SendBase = y
if (当前还有没有确认的报文段)
启动定时器
}
else {
值为 y的重复确认的次数加1
if (值为 y的重复确认的计数= 3) {
重传序号位y的报文段
}
###流量控制
流量控制:发送方不能发送太多、太快的数据让接收方缓冲区溢出
工作原理:
接收方在报文段接收窗口字段中通告其接收缓冲区的剩余空间,发送方要限制未确认的数据不超过RcvWindow
发送方:LastByteSent-LastByteAcked <或= RcvWindow
接收方:RcvWindow = RcvBuffer-[LastByteRcvd - LastByteRead]
LastByteSent:最后一个发送的字节编号;LastByteAcked:最后一个被确认的字节编号,它们相减就是已经发送还未被确认的数据量
###连接管理
TCP是面向连接的协议,TCP连接的建立和释放是每次TCP传输中必不可少的过程,三个过程
-
连接建立(三次握手)
- SYN :同步序列编号(Synchronize Sequence Numbers)
- SEQ : 序列号(Sequence Number)
- ACK :确认编号(Acknowledgement Number)
过程:
-
客户机向服务器发送 TCP SYN报文段
-
指定初始序号
-
没有数据
-
-
服务器收到SYN报文段, 用SYNACK报文段回复
- 服务器为该连接分配缓冲区和变量
- 指定服务器初始序号
-
: 客户机接收到 SYN,ACK, 用ACK报文段回复,可能包含数据
-
数据传输
没啥好讲的,建立连接后就是数据传输 -
连接释放(四次挥手)
- 客户机向服务器发送TCP FIN控制报文段
- 服务器收到FIN,用ACK回答。关闭连接,发送FIN
- 客户机收到FIN, 用ACK答 ,进入 “超时等待” – 将对接收到的FIN进行确认
- 服务器接收ACK,连接关闭
总结:TCP连接的客户端生命周期
TCP连接服务器生命周期:
3.6 拥塞控制的原理
当大量的分组进入网络,超出了网络的处理能力时,会引起网络局部或整体性能下降,这种现象称为拥塞。不加控制的拥塞甚至导致整个网络瘫痪
不同于流量控制
- 流量控制是端到端,接收方控制发送方的传输速率,如下图a
- 拥塞控制是发送方通过发送和响应的情况,获取网络链路的拥塞状况,来调整自身的发送速率,如下图b
拥塞的原因与开销
更实际的情况,当分组丢失时, 任何用于传输该分组的上游传输能力都被浪费!
两类拥塞控制方法
- 端到端的拥塞控制
- 不能从网络得到明确的反馈
- 从端系统根据观察到的时延和丢失现象推断出拥塞
- 这是TCP所采用的方法
- 网络辅助的拥塞控制
- 路由器为端系统提供显示反馈(一个bit指示一条链路出现拥塞,指示发送方按照一定速率发送)
3.7 TCP拥塞控制
发送方根据所“感知”到的网络拥塞程度来“限制”发送速率
发送方传递的速率是根据这个公式来的
LastByteSent-LastByteAcked≤min{cwnd,rwnd}
TCP拥塞控制算法
-
慢启动
当连接开始,以指数增加速率,直到第一个丢失事件发生,将拥塞窗口设为1
-
拥塞避免
为了防止过快增长,更加准确达到拥塞值,拥塞窗口转为线性增长,一个RTT只增加一个MSS问题: 什么时候从指数增长转变为线性增长?
回答: cwnd达到它超时以前1/2的时候.
阈值:ssthresh,阈值ssthresh设置为发生丢失以前的cwnd的一半
-
快速恢复
分为两种情况,一个是TCP收到3个冗余确认后,进行快速恢复;另一个是超时事件后重传
- 超时重传:Cwnd值设置为1 MSS,进入慢启动
- 快速重传:Cwnd减半
3个冗余ACK指示网络还具有某些传送报文段的能力
“超时” 则拥塞更为 “严重”
- 超时重传:Cwnd值设置为1 MSS,进入慢启动
TCP拥塞控制FSM描述
总结:
- 当cwnd < ssthresh时,发送者处于慢启动阶段, cwnd指数增长
- 当cwnd > ssthresh时,发送者处于拥塞避免阶段, cwnd线性增长
- 当出现3个冗余确认时, 阈值ssthresh设置为cwnd/2,且cwnd设置为ssthresh
- 当超时发生时,阈值ssthresh设置为cwnd/2,并且cwnd设置为1 MSS.
###TCP吞吐量
作为窗口长度和RTT的函数,TCP的平均吞吐量是什么?(忽略慢启动)
如果窗口为 W,吞吐量是 W/RTT
当丢包发生后,窗口降为 W/2,吞吐量为 W/2RTT.
一个连接的平均吞吐量为0 .75 W/RTT
###TCP公平性
如果K个 TCP 会话 共享带宽为 R的链路瓶颈, 每个会话应有R/K的平均链路速率
破坏公平的方式有两种:
- 使用UDP
- 多个并行TCP连接