传输层
- 单元知识框架
- 3.1 transport-layer services
- 3.2 multiplexing and demultiplexing
- 3.3 connectionless transport: UDP
- 3.4 principles of reliable data transfer
principles of reliable data transfer - 3.5 connection-oriented transport: TCP
- segment structure
- reliable data transfer
- flow control
- connection management
- 3.6 principles of congestion control
- 3.7 TCP congestion control
transport-layer services(传输层服务)
传输层服务和协议
- 传输层服务:在不同主机上运行的应用程序进程之间提供逻辑通信(logical communication)
- 端系统运行传输层协议
- 发送方:将应用递交的消息(报文)分成一个或多个的报文段(segment),并向下传给网络层
- 接收方:将接收到的报文段重新组装(reassembles)成消息,并上交给应用层
- 传输层可以为应用提供多种协议
- TCP
- UDP
传输层与网络层的区别
- 网络层
- 提供主机之间的逻辑通信
- 传输层
- 提供应用进程之间的逻辑通信
Internat传输层协议
- 可靠、按序的交付服务(TCP)
- 拥塞控制
- 流量控制
- 连接建立
- 不可靠,不按序的交付服务(UDP)
- 基于“尽力而为(best-effort)”的网络层
- 没有做(可靠性方面的)扩展—>frill装饰性的
- 两种服务均不保证
- 带宽
- 延迟
multiplexing and demultiplexing(多路复用与多路分用)
- 运输层的多路复用与多路分用概念
- 多路复用:发送端的传输层处理(handle)来自多个sockets(来自应用层)的数据,为每块数据封装上头部信息,生成报文段,交给网络层
- 多路分用:接收端的传输层依据头部信息将收到的报文段交给正确的Socket,即不同的进程
多路分用的工作流程
- 主机接收到IP数据报(网络层)
- 每个数据报携带源IP地址和目的IP地址
- 每个数据报携带一个传输层的段
- 每个段携带源端口号和目的端口号
- 主机接收到段(传输层)
- 运输层检查报文段的目的端口号,将段定向到相应的中间的socket,然后报文段数据根据套接字进入其所连接的进程
无连接多路分用的UDP
- 发送方
- 利用端口号创建套接字socket
DatagramSocket mySocket1= new DatagramSocket(12534);
- UDP的socket用二元组标识
- 目的IP地址和目的端口号
- 利用端口号创建套接字socket
- 接收方
- 主机接收到UDP段后
- 检查段中的目的端口号
- 将UDP段导向绑定在该端口号的socket
- 如果两个UDP报文段有着不同的源IP地址和/或源端口号,但具有相同的目的IP地址和目的端口号。那么它们将通过相同的套接字被定向到相同的目的进程
- 主机接收到UDP段后
面向连接(Connection-oriented)多路分用的TCP
- TCP的socket用四元组标识
- 源IP地址,源端口号
- 目的IP地址,目的端口号
- 接收端利用所有的四个值将段定向到合适的socket
- 服务器可能同时支持多个TCP sockets
- 每个socket用自己的四元组标识
- Web服务器为每个客户端开不同的socket
- 持久HTTP,在整个连接持续期间,都在使用同一套接字交换报文
- 非持久HTTP,每个请求/响应都创建一个新的TCP连接并在随后关闭
- TCP的Socket用四元组标识。即使目的地址和目的端口相同,如果具有不同源地址或者源端口,TCP报文段将会定向到不同的套接字
- 故而有了多线程Web服务器,服务器端同一端口并行执行多个UDP连接
- 线程可以看成一个轻量级的子进程
- 故而有了多线程Web服务器,服务器端同一端口并行执行多个UDP连接
无连接的传输:UDP
UDP:用户数据报协议
- UDP协议是基于IP协议的,它提供了上节的多路复用/分用,同时也增加了一些简单的错误校验。
- UDP提供的服务是“Best effort”服务(尽力而为的服务),UDP段①可能丢失,②非按序到达
- 无连接
- UDP发送方和接收方之间不需要握手
- 每个UDP段的处理独立于其他段
- UDP的使用
- 流媒体应用
- 容忍丢失
- 速率敏感
- DNS
- SNMP
- 流媒体应用
- 在UDP上如何实现可靠数据传输
- 在应用层增加可靠性机制
- 应用特定的(specific)错误恢复机制
- UDP报头
- length:UDP段的长度(包含头部)
- checksum:校验和
- 为什么要有一个UDP?
- 无需建立连接(减少延迟)
- 实现简单,无需维护连接状态
- 头部开销少
- 没有拥塞控制,应用可更好地控制发送时间和速率
UDP校验和
- 为什么要UDP要进行检验和计算(差错校验):不能保证源和目的之间的所有链路层都提供差错检测
- 目的:检测UDP段在传输中是否发生错误(如:位翻转,即0变1,1变0)
- 发送方
- 将段的内容视为16-bit整数
- 校验和计算:计算所有整数的和,进位加在和的后面,将得到的值按位取反,得到校验和
- 发送方将校验和放入校验和字段
- 接收方
- 计算所收到段的校验和
- 将其与校验和字段进行对比
- 不相等:检测出错误(error detected)
- 相等:没有检测出错误(但可能有错误)
- 举个栗子
- 注意:最高位进位必须被加进去
principles of reliable data transfer(可靠数据传输原理)
- 可靠指的是不错(0变成1)、不丢(分组丢失)、不乱(按照发送顺序进行交付)
- 可靠数据传输协议基本结构:接口
构造可靠的数据传输协议
-
我们将
- 逐步(incrementally)开发可靠数据传输协议(rdt)的发送方和接收方
- 仅考虑单向的(unidirectional)数据传输
- 但是注意控制信息是双向流动的!
- 采用有限(finite)状态机FSM具体描述(刻画)发送方与接收方(传输协议)
-
1.rdt1.0:经完全可靠信道的可靠数据传输
- 底层信道完全可靠
- 不会发生错误(no bit error)
- 不会丢弃分组
- 也是按顺序到达
- 发送方和接收方的FSM独立
- make_pkt(data)只是为了产生一个包含高层数据的分组
- extract(packet,data)只是为了从分组中提取出来数据
- 注意:由于是100%可靠,所以只需发,无需控制,所以FSM有限状态机独立
- 底层信道完全可靠
-
2.rdt2.0:经具有比特差错信息的可靠数据传输
- 底层信道可能翻转(flip)分组中的位,但是不会产生丢包和乱序
- 解决方案:利用校验和检测位错误
- 如何从错误中恢复?
- 确认机制(acknowledgements(ACKs)):接收方显式地(explicitly 明确地)告知发送方分组已正确接收
- 否认确认机制(negative acknowledgements(NAKs)):接收方显式地告知发送方分组有错误
- 发送方接收到NAK以后,重新传输分组
- 基于这种重传机制的rdt协议称为ARQ(Automatic Repeat reQuest)协议
- 基于rdt1.0,rdt2.0中引入的新机制
- 差错检测(error detection)
- 反馈:来自接收方的控制消息ACK/NAK
- 重传
- FSM工作流程
- 停-等协议:当发送方处于等待ACK或NAK的状态的时候,rdt_send()事件不可能出现;仅当接收到ACK并离开该状态时才能发生这样的事件,因为收到ACK分组,协议就会返回到等待来自上层数据的状态
- 底层信道可能翻转(flip)分组中的位,但是不会产生丢包和乱序
-
rdt2.0有什么缺陷?(has a fatal flaw!有致命的缺陷)
- 如果ACK/NAK消息发生错误/被破坏(corrupted)会怎么样?
- 为ACK/NAK增加校验和,检错并纠错
- 发送方收到被破坏的ACK/NAK时不知道接收方发生了什么,添加额外的控制信息
- 如果ACK/NAK坏掉,发送方重传当前分组
- 不能仅仅简单的重传:可能产生不必要的重复(duplicate不必要的重复)分组
- 如何解决(handle)重复分组问题?
- 序列号(sequence number):发送方给每个分组增加序列号
- 接收方丢弃(discard 丢弃)重复分组
- 如果ACK/NAK消息发生错误/被破坏(corrupted)会怎么样?
-
rdt2.1:加入新的机制,序列号机制
- 完美的解决了重复分组问题
-
rdt2.2:将NAK去掉(不需要),用ACK确认最后的一个分组,可以代替它
-
3.rdt3.0:经具有比特差错信息的丢包信道的可靠数据传输
- 新的假设
- 底层信道既可能发生错误,也可能丢失分组(data,ACKS)
- 校验+序列号+ACK+重传有帮助,但是不够用
- 解决方法:发送方等待“合理”时间
- 如果没有收到ACK,重传
- 如果分组或ACK只是延迟而不是丢了
- 重传会产生重复,序列号机制能够处理
- 接收方需指定由ACK所确定的分组的序列号
- 需要定时器
- 底层信道既可能发生错误,也可能丢失分组(data,ACKS)
- rdt3.0性能分析
- rdt3.0是一个功能比较完善,可以实际使用的协议,但是性能很糟糕(stink 让人觉得很糟糕)
- 举个栗子:带宽1Gbps的链路,端到端的传播时延15ms,需要传输8000bit的分组
- 发送时延(传输时延):d=L/R,L 为分组长度,R 为链路带宽。l=8000/10^9=8msecs毫秒
- 发送方(信道)利用率(utilization 利用率)—fraction(少量),停等协议有着非常低的发送方利用率
- 如果RTT是30msec,每30msec发送1kB的分组,那么1Gbps链路的吞吐量为33KB/sec(1sec/30msec=x/1KB;x=33KB)
- 网络协议极大地限制了物理资源的使用
- 新的假设
流水线机制
- 什么是流水线机制
- 不用停等方式运行,发方允许多个,传输途中,仍未被确认的分组进行传输
- 流水线机制对于可靠数据传输协议带来了几个影响:
- 更大的序列号范围,1bit已经完全不能满足了
- 发送方和/或接收方需要更大的存储空间以缓存分组
- 两种通用的(generic)流水线协议
- 回去N步go-back-N:GBN
- 选择重传selective repeat:SR
- GBN
- 发方可以发送多个未被确认的(unacked)分组无需等待,高达N
- 接收方仅仅发送累积(cumulative 累积的)ACK
- 如果分组间有间隙,则不确认分组
- 发方会为最早发出而未被确认的分组设置计时器
- 当计时器超时(expire到期,超时),发方重传定时器开始以后的所有未确认分组
- SR
- 发方可以发送多个未被确认的(unacked)分组无需等待,高达N
- 收方对每一个分组独立发送(individual(ɪndɪˈvɪdʒuəl)单独的,个人的)确认
- 发方为每一个未确认的分组设置定时器
- 当计时器超时,发方仅仅重传那些未确认的分组,避免不必要的重传
GBN
- 发送方
- 分组首部需要k bit的序列号,n=2^k,n为序号空间的大小,窗口在序号空间中向右滑动
- ACK(n):表示序列号n之前的所有分组都已经被确认,包括n在内—>累积ACK
- 可能会收到重复的ACK
- 设置定时器给黄色最左边的那个,它是最早的传输的未被确认的分组
- 如果给序列号n设置定时器并且超时,那么重传窗口中所有更高序号的未被确认的分组
- default在接收方丢弃分组之后会为最近按序接收的分组重新发送ACK,从而导致可能产生重复的ACK;
SR
- 接收方单独确认所有正确接受的分组
- 设置缓冲机制,缓冲乱序到达的分组。(根据需要来缓冲分组,以便最终按序交付到上层)
- 发送方只重传那些没收到ACK的分组
- 发送方为每个分组设置了定时器
- 发送方窗口
- N个连续的(consecutive kənˈsekjətɪv连续的)序列号
- 限制已发送的且未确认的分组的序号
- 发送方接收方的窗口图示
- 发送方
- 从上层收到数据
- 如果下一个可用序号在窗口中,则打包发送分组
- 分组n超时
- 重传分组n,重新设置定时器
- 收到ACK(n)
- 如果分组序号窗口内,发送方标记分组n为已接收
- 如果分组序号恰好等于send_base,则把窗口基序号向前移动到具有最小序号的未确认分组处
- 从上层收到数据
- 接收方
- 如果分组n在当前窗口内
- 发送ACK(n)给发送方
- 如果是失序的话,缓存该分组
- 如果分组序号等于接收窗口的基序号,则该分组以及以前缓存的序号与该分组连续的交付给上层,以及向前滑动窗口到未收到分组的序号,总之就是保证窗口宽度为N
- 如果分组n在当前窗口之前,则分组是收方之前确认过的
- 再次发送ACK(n)
- 其他情况,直接忽略该分组
- 如果分组n在当前窗口内
- 进退两难的窘境
- 发方与收方窗口间缺乏同步
- SR接收方窗口太大的困境:收到的到底是一个新的分组还是一次重传
- 窗口长度必须小于等于序列号空间大小的一半
面向连接的传输:TCP
TCP连接
- 点对点
- 一个发送方,一个接收方
- 可靠的,按序的字节流
- 流水线机制
- TCP拥塞控制和流量控制机制设置窗口尺寸
- 发送方/接收方缓存
- 全双工(full-duplex)服务
- 同一连接中能够传输双向(bi-directional)数据流(data flow)
- MSS:最大报文段长度
- 面向连接
- 在数据交换之前握手(交换控制信息)以初始化发送方和接收方的状态
- 连接状态只在连接的两端中维护,在沿途节点(路由器和链路层交换机)中并不维护状态
- TCP连接包括:两台主机上的缓存,连接状态变量,socket等
- 流量控制机制
- 发送方不会淹没接收方
TCP报文段结构(segment structure)
- TCP的报文段结构
- 首部字段
- 源端口号和目的端口号:用于多路复用和多路分用
- 序号和确认号:用于实现可靠数据传输服务
- 首部长度字段
- 保留未用字段
- 标志字段:ACK用于确认字段是否有效、RST、SYN、FIN用于连接的建立和拆除(setup,teardown)
- 接收窗口:用于流量控制,该字段指示接收方愿意接收的字节数量
- 因特网校验和:差错检验
- 紧急数据指针(pointer)
- 可选与变长的选项字段:用于双方协商最大报文长度,或在高速网络环境下用于窗口调节因子
- 数据字段
- 首部字段
- TCP的序号和确认号
- 序号(sequence numbers)
- 报文段中的第一个字节的编号,不是报文段的编号
- 确认号(ACKS)
- 主机A填充进报文段的确认号是主机A期望从主机B收到的下一字节的编号
- TCP只确认该流中至第一个丢失字节为止的字节,所以TCP被称为提供累计确认
- Q:接收方如何处理失序的报文段
- A:两种选择,一是立即丢弃,二是保留失序字节
- 序号(sequence numbers)
- telnet:序号和确认号的一个学习案例
TCP往返时间(round trip time)的估计与超时(偏理论,感兴趣的可以看论文)
- TCP也采用超时/重传机制
- Q:如何设置超时间隔长度?(timeout value)
- 定时器超时时间肯定大于RTT
- 但是RTT是变化的
- 太短
- 过早(premature)超时
- 不必要的重传
- 太长
- 对数据段的丢失反应慢
- 定时器超时时间肯定大于RTT
- Q:如何估计(estimate)RTT?
- 报文段的样本RTT(SampleRTT):测量从段发出到收到ACK的时间
- 忽略重传
- SampleRTT是变化的
- 测量多个SampleRTT取平均,而不只是用当前的SampleRTT
- EstimatedRTT:SampleRTT均值
- 报文段的样本RTT(SampleRTT):测量从段发出到收到ACK的时间
- RTT偏差DevRTT
- 实质就是一种安全界限(safety margin)
- 用于估算SampleRTT一般会偏离EstimatedRTT的程度
定时器时间设置:TimeoutInterval = EstimatedRTT + 4*DevRTT
TCP可靠数据传输
- 可靠数据传输
- TCP在IP层提供的不可靠服务的基础上实现可靠数据传输服务
- 流水线机制
- 累计确认机制
- 单一的重传定时器
- 触发(trigger)重传的事件
- 定时器超时事件
- 收到重复的ACK
- TCP在IP层提供的不可靠服务的基础上实现可靠数据传输服务
- TCP发送方处理事件
- 从应用层收到数据
- 使用序列号创建segment
- 序列号是segment的第一个字节的编号
- 如果定时器还没有运行,开启定时器
- 定时器与最早的未确认的分组有关
- 过期间隔(expiration interval):设置超时时间TimeOutInterval
- 超时
- 重传引起超时的分组
- 重启定时器
- 收到ACK
- 如果确认此前未确认的segment
- 更新sendbase
- 如果更新后,窗口还有未被确认的分组,重新启动定时器(单一重传)
- 如果确认此前未确认的segment
- 从应用层收到数据
- TCP接收方处理事件
- 不使用NAK
- 产生冗余ACK表示传输的分组丢失等情况
- 快速重传
- 一旦收到三个冗余ACK,TCP就执行快速重传
- TCP的差错恢复机制可以看成GBN与SR的混合体
TCP流量控制
- 发送方控制接收方,以便保证发送方不会因为发送太多,太快,数据溢出接收方的缓存
- 流量控制实际上是一个速度匹配服务
- Q:接收方告诉发送方rwnd=0,会发生什么情况?
- A:发送方停止发送数据,并启动持续计时器(持续计时器超时时间就是重传时间)开始计时,持续计时器超时以后,发送方发送探测报文(探测报文的序号会消耗一个字节数据)
TCP连接管理:3次握手,4次挥手
- 第一次握手
- 客户端的TCP向服务器端的TCP发送特殊的TCP报文段(SYN报文段)
- 不包含应用层数据
- 标志位(SYN比特)被置为1
- 随机选择一个初始序号x,给序号字段
- SYN报文段(SYN=1的报文段)不能携带数据,但需要消耗掉一个序号
- 客户端的TCP向服务器端的TCP发送特殊的TCP报文段(SYN报文段)
- 第二次握手
- 服务器提取出SYN报文段,为该TCP连接分配TCP缓存和变量,并向客户端发送允许连接的报文段(SYNACK报文段)
- 不包含应用层数据
- SYN比特置为1
- 确认号字段置为x+1
- 随机选择初始序号y,给序号字段
- ACK置为1
- 报文段的含义:我收到了你发起建立连接的SYN分组,该分组带有初始序号x。我同意建立该连接。我自己的初始序号是y。
- 报文段不能携带数据,但是同样要消耗一个序号。
- 服务器提取出SYN报文段,为该TCP连接分配TCP缓存和变量,并向客户端发送允许连接的报文段(SYNACK报文段)
- 第三次握手
- 收到SYNACK报文段后,客户也要给该连接分配缓存和变量
- 确认字段置为y+1
- SYN比特置为0
- ACK置为1
- 序号字段置为x+1
- 报文段可以携带数据,但是如果不携带数据则不消耗序号
- 收到SYNACK报文段后,客户也要给该连接分配缓存和变量
- 第一次挥手
- 客户端进程发起连接释放报文,并且停止发送数据
- FIN=1
- seq=u(u是前面传过来的数据的最后一个字节加1)
- FIN报文段即使不携带数据,也要消耗一个序号
- 客户端进程发起连接释放报文,并且停止发送数据
- 第二次挥手
- 服务器收到连接释放报文,发出确认报文
- ACK=1
- 确认号u+1
- 序号为v
- TCP服务器通知高层的应用进程,客户端向服务器的方向就释放了,这时候处于半关闭状态,即客户端已经没有数据要发送了,但是服务器若发送数据,客户端依然要接受。这个状态还要持续一段时间,也就是整个CLOSE-WAIT状态持续的时间。
- 服务器收到连接释放报文,发出确认报文
- 第三次挥手
- 服务器等待数据发送完毕,就发送连接释放报文
- FIN=1
- 确认号u+1
- 序列号w
- 服务器等待数据发送完毕,就发送连接释放报文
- 第四次挥手
- 客户端收到释放报文后,必须发出确认
- ACK=1
- 确认号w+1
- 序列号u+1
- 当客户端撤销相应的TCB后,才进入CLOSED状态
- 客户端收到释放报文后,必须发出确认
- 服务器结束TCP连接的时间要比客户端早一些
拥塞控制原理
- 拥塞
- 非正式的定义:太多主机发送了太多数据或者发送速度太快,以至于网络无法处理(handle)
- 不同于流量控制
- 表现(manifestations 显示,表明)
- 分组丢失(路由器缓存溢出)
- 分组延迟过大(在路由器缓存中排队)
拥塞的成因(cases)和代价(costs)
- 拥塞的成因与代价
- 当分组的到达速率接近链路容量的时候,分组经历巨大的排队时延
- 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组
- 发送方在遇到大时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本
- 当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉
拥塞控制方法
- 端到端的拥塞控制(TCP)----->重点
- 网络层不需要显式的提供回馈
- 端系统通过观察loss,delay等网络行为判断(infer 推断,推理)是否发生拥塞
- 网络辅助的拥塞控制
- 路由器向端系统(发送方)显式地反馈网络拥塞信息
- 简单的拥塞指示(1bit):SNA, DECbit, TCP/IP ECN, ATM)
- 指示发送方应该采取何种速率
- 路由器向端系统(发送方)显式地反馈网络拥塞信息
TCP的拥塞控制
- TCP拥塞控制的解决方法
- 让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率
- 路径没有拥塞,加快发送速率
- 路径有拥塞,减小发送速率
- 让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率
- 面临三个问题
- 一个TCP发送方如何限制它向其连接发送流量的速率呢?
- 一个TCP发送方如何感知从它到目的地之间的路径上存在拥塞呢?
- 当发送方感知到端到端的拥塞时,采取何种算法来改变其发送速率呢?
TCP拥塞控制的基本原理
- 问题一:首先是如何限制TCP发送方向连接发送的流量速率
- 主要采取的方式是 控制拥塞窗口cwnd的大小
- 主要采取的方式是 控制拥塞窗口cwnd的大小
- 问题二:其次是如何使发送方感知网络拥塞
- 定义’丢包事件’:要么出现超时,要么收到来自接收方的三个冗余ACK
- 丢包事件则意味着拥塞
- 问题三:最后是如何合理的调整发送速率
- 主要采用的是TCP拥塞控制算法
TCP拥塞控制:加性增-乘性减(AIMD)算法
- 原理:逐渐增加发送速率(窗口大小),谨慎探测(probe)可用带宽,直到发生loss
- 加性增:每个RTT增大cwnd 1MSS,直到检测到分组丢失
- 乘性减:发生分组丢失以后,将cwnd减半
- 锯齿行为:探测可用带宽
- cwnd:TCP发送方拥塞窗口大小
TCP拥塞控制算法
- 慢启动(SS),拥塞避免(CA),快速恢复(FR)
- 慢启动的开始
- 检测,感应丢包
- TCP RENO(重点)
- 由超时指示的丢包事件----->慢启动处理
- cwnd设置为1MSS,重新开启慢启动
- cwnd然后以指数方式增长到阈值(threshold 阈值),然后以线性方式增长
- 阈值:当检测到拥塞时将threshold置为拥塞窗口值的一半,即cwnd/2
- 由3个冗余ACK指示的丢包事件------>快速恢复处理
- 重复的ACK表明网络能够传送一些段(比如ACK或者数据段)
- cwnd被置为阈值,然后线性增长
- 阈值:阈值减到拥塞时窗口的一半,即cwnd/2
- 由超时指示的丢包事件----->慢启动处理
- TCP Tahoe
- 由超时指示的丢包事件或者由3个冗余ACK指示的丢包事件
- cwnd设置为1MSS,重新开启慢启动
- cwnd然后以指数方式增长到阈值(threshold 阈值),然后以线性方式增长
- 阈值:当检测到拥塞时将threshold置为拥塞窗口值的一半,即cwnd/2
- 由超时指示的丢包事件或者由3个冗余ACK指示的丢包事件
- TCP RENO(重点)
- 慢启动的开始