传输层
传输层服务的基本理论和基本机制:
- 多路复用/分用
- 可靠数据传输机制
- 流量控制机制
- 拥塞控制机制
Internet的传输层协议
- UDP: 无连接传输服务
- TCP: 面向连接的传输服务
- TCP拥塞控制
主机上运行着五层Internet协议栈,有应用层、传输层、网络层、数据链路层和物理层;路由器上只有三层协议栈,即网络层及以上的是没有的。
传输层协议为运行在不同host上的进程提供了一种逻辑通信机制。
逻辑通信机制,就是指进程之间仿佛是直接连接的,不需要关心有多远的物理距离、经过了多少个路由器、使用的是什么物理媒介。
端系统运行传输层协议:
- 发送方:将应用递交的消息分成一个或多个的segment,并向下传给网络层。
- 接收方:将接收到的segment组装成消息,并向上交给应用层。
传输层可以为应用提供多种协议:
- Internet上的TCP
- Internet上的UDP
比较
网络层:提供主机之间的逻辑通信机制
传输层:提供应用进程之间的逻辑通信机制
— 位于网络层之上(IP),依赖于网络层服务,对网络层进行(可能的)增强
Internet传输层协议
可靠、按序的交付服务(TCP)
- 拥塞控制
- 流量控制
- 连接建立
不可靠的交付服务(UDP)
- 基于”尽力而为 (best-effort) “的网络层,没有做(可靠性方面的)扩展
两种服务均不提供:延迟、带宽
多路复用和多路分用
为什么要多路复用/分用?
- 如果某层的一个协议对应直接上层的多个协议/实体,则需要复用/分用。
socket是应用层和传输层之间的”门”。
接收端进行多路分用:传输层依据头部信息将收到的segment交给正确的socket,即不同的进程。
发送端进行多路复用:从多个socket接收数据,为每块数据封装上头部信息,生成segment,交给网络层。
分用——如何工作?
主机接收到 IP 数据报(datagram)
- 每个数据报携带源 IP 地址、目的 IP 地址
- 每个数据报携带一个传输层的段(segment)
- 每个段携带源端口号和目的端口号
TCP/UDP 段格式:
|——————- 32 bits ——————-|
| 源端口号 | 目的端口号 |
| 其他头部信息 |
| 应用数据 (message) |
主机收到segment后,传输层协议提取IP地址和端口号信息,将segment导向相应的socket。(网络层是不关心端口号信息的)TCP会做更多的处理。
无连接分用
UDP的socket用二元组标识(目的IP地址,目的端口号)
主机收到UDP段后:
- 检查段中的目的端口号
- 将UDP段导向绑定在该端口号的socket
来自不同源IP地址和/或源端口号的IP数据包被导向同一个socket。
面向连接分用
TCP的socket用四元组标识:
- 源IP地址
- 源端口号
- 目的IP地址
- 目的端口号
接收端利用所有的4个值将segment导向合适的socket。
服务器可能同时支持多个TCP socket。每个socket用自己的四元组标识。
web服务器为每个客户端开不同的socket。
也就是说,例如host B中的进程1向host A发起TCP连接,SP(source port)是9157,DP是80;进程2也发起TCP连接,SP是5775,DP是80;两个进程的S-IP和D-IP相同,都是B和A。但是socket不同,服务器为每个客户端开不同的socket。进程1对应socket1,进程2对应socket2。服务器上的这两个socket的SP相同,都是80,S-IP和D-IP也分别相同,但是DP不同,分别是5775和9157.
UDP
User Datagram Protocol [ RFC 768 ]
基于Internet IP协议:
- 复用/分用
- 简单的错误校验(因为路由器在存储转发的过程中也可能会出错)
UDP提供的是”Best effort”服务,所以会丢失、非按序到达。
每个UDP段的处理独立于其他段。
UDP为什么存在?
- 无需建立连接(减少延迟,因此DNS使用的是UDP)
- 实现简单:无需维护连接状态
- 头部开销少(UDP头部8个字节,而TCP是20个字节)
- 没有拥塞控制:应用可以更好地控制发送时间和速率(TCP有拥塞控制,会根据实际情况自动调整发送时间和速率)
常用于流媒体应用:容忍丢失、速率敏感
UDP还用于:DNS,SNMP
在UDP上是可以实现可靠数据传输的——在应用层增加可靠性机制、应用特定的错误恢复机制(即在应用层实现,因此对应用层开发人员来说难度较大)
UDP segment format:
[32bits]
| sp | dp |
| length | checksum |
| Application data (message)|
length是UDP段的长度(包含头部),checksum是校验和(实现错误校验功能)。
UDP checksum
目的:检测UDP段在传输过程中是否发生错误(如位翻转)。
发生错误是因为传输是端到端的,可能经历了多种物理媒介、多个路由器等等,中途很有可能发生错误。
发送方:
- 将段的内容视为16-bit整数
- 校验和计算:计算所有整数的和,进位单独取出来与剩下的16位相加,将得到的值按位求反,得到校验和
- 发送方将校验和放入校验和字段
接收方:
- 计算所收到的校验和
- 将其与校验和字段进行对比,若不相等则检测出错误,若相等则没有检测出错误,但仍然可能有错误
可靠数据传输原理
可靠——不错、不丢、不乱
可靠数据传输协议:
- 可靠数据传输对应用层、传输层、链路层都很重要
- 网络top-10问题
- 信道的不可靠特性决定了可靠数据传输协议 (rdt) 的复杂性
可靠数据传输协议基本结构:接口
rdt_send(): 被上层应用调用,将数据交给rdt (reliable data transfer protocol) 以发送给对方。即发送方向上地响应这样一个rdt_send的调用。
udt_send(): 被rdt调用,在不可靠信道(unreliable channel)上向接收方传输数据。(所谓的不可靠信道,实际上就是我们所说的网络层的IP协议)
rdt_rcv(): 当数据包到达接收方信道时被调用。这一调用就会触发接收方的rdt协议对数据包进行处理。
deliver_data(): 被rdt调用,向上层应用交付数据。
可以看出,rdt_send()和deliver_send()是单向的。这是因为应用层只需要发数据和收数据,不关心数据是怎么处理和传输的。剩下的所有工作都由下面的层完成。
可靠数据传输协议
渐进的设计可靠数据传输协议的发送方和接收方,只考虑单向数据传输,但控制信息双向流动。利用有限状态机(Finite State Machine, FSM)刻画传输协议。
协议:(逐步贴近真实情况)
Rdt 1.0: 可靠信道上的可靠数据传输
假设底层信道完全可靠:不会发生位错误,不会丢弃分组
发送方和接收方的FSM独立(因为这是一个可靠信道!发送方和接收方之间就不需要什么交互,全部交给协议处理就行了)
Rdt 2.0: 产生位错误的信道
假设分组不会丢失,只是产生了位错误。
首先,接收方需要知道分组是否出错。如果错了,就要想办法恢复/重传。
检测出错已解决——底层信道可能翻转分组中的位(bit):利用校验和检测位错误
如何从错误中恢复?这就需要引入新的控制消息来标识——
- 确认机制(Acknowledgements, ACK):接收方显示地告知发送方分组已正确接收。
- NAK:接收方显示地告知发送方分组有错误。
- 发送方收到NAK后,重传分组。
基于这种重传机制的rdt协议称为ARQ(Automatic Repeat Request)协议。
Rdt 2.0中引入的新机制:
- 差错检测
- 接收方反馈控制消息:ACK/NAK
- 重传
但是有一个致命缺陷:如果ACK/NAK的传输出错怎么办?这里使用的是停-等协议,即stop and wait — sender sends one packet, then waits for receiver response.
what happens if ACK/NAK corrupted?
sender doesn’t know what happened at receiver!
can’t just retransmit: possible duplicate
Handling duplicates:
sender retransmits current pkt if ACK/NAK corrupted
sender adds sequence number to each pkt
receiver discards (doesn’t deliver up) duplicate pkt
Rdt 2.1 发送方应对ACK/NAK破坏
增加了两个序列号0和1。
对于发送方,有等待上层调用的状态和等待ACK/NAK的状态这两种,因此总状态是翻倍了的,即两个0两个1。(等待上层调用序列号0分组的状态,等待序列号0的ACK/NAK的状态,等待上层调用序列号1分组的状态,等待序列号1的ACK/NAK的状态)翻倍是因为必须记住当前分组的序列号。
Rdt 2.2: 无NAK消息协议
接收方通过ACK告知最后一个被正确接收的分组,在ACK中显示地加入被确认分组的序列号。
发送方接收到重复ACK后,重发当前分组。
停等操作使得Rdt 3.0的性能很差。
流水线协议
允许发送方在收到ACK之前连续发送多个分组。这就需要更大的序列号范围,发送方和接收方需要更大的存储空间以缓存分组。
滑动窗口协议 Sliding-window protocol
窗口:允许使用的序列号范围
窗口尺寸为N,表示最多有N个等待确认的消息。
滑动窗口:随着协议的运行,窗口在序列号空间内向前滑动。
滑动窗口协议:GBN,SR
GBN协议 (Go-Back-N)
分组头部包含k-bit序列号
采用累积确认的机制
ACK(n): 确认到序列号n(包含n)的分组均已被正确接收。
超时timeout(n)事件:重传序列号大于等于n,还未收到ACK的所有分组。
ACK机制:发送拥有最高序列号的、已被正确接收的分组的ACK
- 可能产生重复的ACK
- 只需要记住唯一的expectedseqnum
乱序到达的分组:
- 直接丢弃——接收方不缓存
- 重新确认序列号最大的、按序到达的分组
SR (Selective Repeat)
接收方对每个分组单独进行确认
- 设置缓存机制,缓存乱序到达的分组
发送方只重传那些没收到ACK的分组
- 为每个分组设置定时器
发送方窗口
- N个连续的序列号
- 限制已发送且未确认的分组
序列号空间大小与窗口尺寸满足的关系:$N_S+N_R\leq2^k$.
TCP
点对点:一个发送方,一个接收方
可靠的、按序的字节流
流水线机制:TCP拥塞控制和流量控制机制设置窗口尺寸
发送方/接收方缓存
全双工 (full-duplex):统一连接中能够传输双向数据流
面向连接:
通信双方在发送数据之前必须建立连接
连接状态只在连接的两端中维护,在沿途节点中并不维护状态
TCP连接包括:两台主机上的缓存、连接状态变量、socket等
流量控制机制
序列号
- 序列号指的是segment中第一个字节的编号,而不是segment的编号,通常从500开始
- 建立TCP连接时,双方随即选择序列号
ACKs
- 希望接收到的下一个字节的序列号
- 累积确认:该序列号之前的所有字节均已被正确接收到
接收方如何处理乱序到达的segment?
- TCP规范中没有规定,由TCP的实现者做出决策
TCP可靠数据传输
TCP在IP层提供的不可靠服务基础上实现可靠数据传输服务
流水线机制
累积确认
TCP使用单一重传定时器
- 触发重传的事件:超时,收到重复ACK
- 渐进式:暂不考虑重复ACK,暂不考虑流量控制,暂不考虑拥塞控制
RTT和超时
如何设置定时器的超时时间?
- 大于RTT——但是RTT是变化的
- 过短:不必要的重传
- 过长:对段丢失时间反应慢
如何估计RTT?
SampleRTT:测量从段发出去到收到ACK的时间
忽略重传
SampleRTT变化,就测量多个取平均值
指数加权移动平均:
EstimatedRTT=(1-alpha)*EstimatedRTT+alpha*SampleRTT
典型值:0.125
TCP发送方要处理的事件
从应用层收到数据:
- 创建segment
- 序列号是segment第一个字节的编号
- 开启计时器
- 设置超时时间TimeoutInterval
超时:
- 重传引起超时的segment
- 重启定时器
收到ACK:
如果确认此前未确认的segment
- 更新SendBase
- 如果窗口中还有未被确认的分组,重新启动定时器
快速重传机制
TCP实现中,如果发生超时,超时时间间隔将重新设置,即将超时时间间隔加倍,导致其很大,因此重发丢失的分组之前要等待很长时间。
通过重复ACK检测分组丢失
如果sender收到对同一数据的3个ACK,则假定该数据之后的段已经丢失,sender重传该分组。
快速重传:在定时器超时之前即进行重传
TCP流量控制
接收方为TCP连接分配buffer。
流量控制 (flow control):发送方不会传输的太多、太快以至于淹没接收方(buffer溢出)。
TCP连接管理
TCP sender和receiver在传输数据前需要建立连接
client是连接发起者,server等待客户连接请求。
Three way handshake
client host sends TCP SYN segment to server
specifies initial seq
no data
server host receives SYN, replies with SYNACK segment
server allocates buffers
specifies server initial seq
client receives SYNACK, replies with ACK segment, which may contain data
TCP关闭——4次挥手
client向server发送FIN
server收到FIN,回复ACK,关闭连接,发送FIN
client收到FIN,回复ACK
- 进入等待状态,timeout了会重复发送ACK
server收到ACK,连接关闭
拥塞控制原理
拥塞(congestion)
表现:
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
拥塞控制的方法
端到端的拥塞控制:
- 网络层不需要显式地提供支持
- 端系统通过观察loss, delay等网络行为判断是否发生拥塞
- TCP采取这种方法
网络辅助的拥塞控制:
- 路由器向发送方显示地反馈网络拥塞信息
- 简单的拥塞只是说
TCP快速重传为什么3次ACK
TCP为什么3次握手
TCP MSS
本文作者 : preccrep
原文链接 : https://preccrep.github.io/2021/05/03/%E4%BC%A0%E8%BE%93%E5%B1%82/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!