计算机与网络(三)---- 运输层
计算机与网络(三)---- 运输层
1.运输层概述与服务
-
运输层:运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信(Logic Communication)。运行不同进程的主机好像直接相连一样。运输层的发送方将应用层的报文分成报文段(Segment),传递给网络层。
-
运输层报文段:
运输层与网络层的对比:
网络层服务:主机之间的逻辑通信
传输层服务:进程间的逻辑通信。传输层服务依赖于网络层的服务,并对网络层的服务进行增强(解决数据丢失、顺序混乱、加密等问题)
-
-
两种不同的运输层协议:
-
UDP(用户数据报协议):不可靠的、不保序的传输
- 多路复用、解复用
- 没有为网络层所提供的服务进行增强
网络层服务IP:IP被称为不可靠服务,IP的服务模型是尽力而为交付服务,它不保证报文段中的数据完整性以及有序性。
-
TCP(传输控制协议):可靠的、保序的传输
- 多路复用、解复用
- 拥塞控制
- 流量控制
- 建立连接
-
2.多路复用与多路分解
-
多路分解(Demultiplexing):将运输层报文段中的数据交付到正确的套接字的工作称为多路分解
-
多路复用(Multiplexing):从不同的套接字中收集数据块,并为每个数据块封装上首部信息从而生成报文段,然后将报文段传递到网络层,称为多路复用。
套接字(Socket):
套接字可以看做是一个标识,是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。
比如TCP的套接字可以看成下面的映射关系
Socket 源IP 源port 目标IP 目标port … UDP套接字:
Socket 源IP 源port … 在Socket编程中:
TCPServer与TCPClient,一个需要绑定到主机的IP地址+端口,另一个需要连接到目标主机的IP地址+端口。而UDP编程中,目标端口与目标IP是在DatagramPacket中指定的,创建UDPSocket仅需要自己的端口号与地址即可。
3.无连接传输:UDP
-
UDP概述
- 尽力而为的服务,报文段可能丢失,乱序
- 无连接,UDP发送端和接受端之间没有握手,每个UDP数据报都被独立的处理
- UDP被应用于流媒体,DNS,SNMP
如何在UDP协议之上实现可靠传输:
- 在应用层增加可靠性
- 应用特定的差错恢复
-
UDP报文结构
-
UDP校验和
- UDP校验和提供了差错检测功能。校验和用于确定当UDP报文段从源到达目的地移动时,其中的比特是否发生了改变。
4.可靠数据传输原理(Reliable Data Transfer Protocol)
如何解决可靠数据传输,在应用层、传输层和数据链路层都很重要。
信道的不可靠特点决定了可靠数据传输协议的复杂性
UDT:不可靠数据传输
-
渐进式构建可靠数据传输协议(仅考虑单向数据传输)
有限状态机(Finite-State Machine,FSM):表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型
-
Rdt1.0:在可靠信道上的可靠数据传输
-
下层信道完全可靠:没有比特出错,没有分组丢失
-
FSM:
-
只需要进行数据的封装与解封装,不需要任何其他的处理
-
-
Rdt2.0:具有比特差错的信道
-
下层信道可能会出错:将分组中的比特翻转
- 使用校验和来检测比特差错
-
需要解决的问题,如何从差错中恢复?
- 确认(ACK):接收方显式地告诉发送发分组已被正确接收
- 否定确认(NAK):接收方显式地告诉发送方分组发送了差错,发送方收到NAK后,发送方重传分组(自动重传请求协议)
-
rdt2.0中的新机制:采用差错控制编码进行差错检测
- 发送方差错控制编码、缓存
- 接收方使用编码检错
- 接收方的反馈:控制报文(ACK,NAK):接收方->发送方
- 发送方收到反馈响应的动作
-
FSM:
当
rdt_send(data)
事件出现时,发送方产生一个待发送数据的分组,带有校验和(checksum),由udt_send发送分组。随后,发送方等待接收方的ACK或者NAK分组,如果是ACK分组即rdt_rcv(rcvpkt)&&isACK(rcvpkt)
,那么说明发送分组已被正确接收。如果是一个NAK分组,那么就需要重传。停等(Stop-And-Wait)协议:只有发送方确信接收方已经正确接收分组时,才会发送新的数据。
接收放在分组到达时,只需要校验分组是否完整,并向发送方响应一个ACK或者NAK报文即可。如果完整,则对改分组进行解封装。
-
存在的缺陷:ACK或者NAK丢失,发送方无法确认接收方是否正确的接收了上一块发送的数据
-
-
Rdt2.1:发送方处理出错的ACK/NAK
-
如何处理?
重传当前数据分组,并为分组加上序号(Sequence Number)。
为什么需要加上序号?
重传数据分组会引入冗余分组。冗余分组的根本困难在于接收方不知道它上次所发送的ACK或NAK是否被发送方正确的收到,所以它无法事先知道接收到的分组时新的还是一次重传。
在分组中加上序号之后,接收方只需要检查序号就可以知道新的分组是否是重传。在停等协议中只需要1个bit位来表示序号即可。
-
FSM:
发送放发送分组0,如果接收到ACK,则继续等待发送分组1,如果NAK则重传,如果无法识别,也重传。
接收方接收到分组0,并且没有出错,然后接收到分组1,也没有出错,那么就正常进行解封装。如果接受方在等待分组1时,接收到了分组0,那么会响应ACK,对该分组不做处理。如果分组错误那么就响应NAK。
-
-
Rdt2.2:无NAK协议
-
功能与2.1相同,但是只使用ACK(ACK需要编号)
-
接收方对最后正确接收的分组发ACK,以替代NAK,当发送方收到重复的ACK时,发送方与接收到NAK时的操作相同:需要重传当前分组
-
FSM:
-
-
Rdt3.0:具有比特差错和分组丢失的信道
-
下层信道不仅会出现比特损失,还会出现分组丢失的情况(数据丢失,ACK丢失)
-
造成的问题:死锁,发送方接收不到确认,接收方接收不到新的分组
-
解决方案:超时重传机制,在一定的时间没有接收到响应(倒计数定时器,Countdown Timer),那么就重传
-
FSM:
-
比特交替协议
过早超时也能正常工作,但是效率较低,一半的分组和确认是重复的。
设置一个合理的超时时间是比较重要的。
-
-
停等协议的缺陷
rdt3.0可以工作,但链路容量比较大的情况下,性能很差。网络协议限制了物理资源的利用。
-
-
流水线可靠数据传输协议
为了解决停等协议所带来的性能瓶颈,不以停等方式运行,允许发送方多个分组而无须等待确认。
-
流水线协议
-
流水线(Pipelining):允许发送方在未得到对方确认的情况下一次发送多个分组
在流水线协议下:
必须增加序号的范围:用多个bit表示分组的序号
在发送方/接收方要有缓存区,发送方需要缓存已经发送的分组,以便于检错重传或超时重传,接收方接受的速率与发送方发送的速率不一致,所以需要缓冲区来对抗两者速度的不一致性。
-
-
滑动窗口(Slide Window)协议
-
基本概念:
-
发送缓冲区
- 形式:内存中的一个区域,落入缓冲区的分组可以发送
- 功能:用于存放已经发送,但是没有得到确认的分组
- 必要性:需要重发时可用.
-
发送窗口
-
发送缓冲区的一个范围
-
发送窗口的最大值<=发送缓冲区的值
-
窗口滑动
真正滑动时,窗口不动,分组移动。
相对滑动时,分组不动,窗口移动。
蓝色表示已经发送并确认的分组
红色表示已经发送未确认的分组
白色表示未发送的分组
发送窗口的大小 =1:相当于停等协议
发送窗口大小 >1,接收窗口大小=1:回退N步(Go-Back-N,GBN)协议
发送窗口>1,接收窗口>1: 选择重传(Selective Repeat,SR)协议
-
-
发送窗口的移动
当已经发送的分组收到确认时,后沿可以向前移动,但是不能超过前沿。
-
接收窗口
-
接收窗口等同于接收缓冲区
-
当接收窗口等于1时,只能顺序接收分组,只有接收到顺序正确的分组之后,窗口才能继续移动。当接收窗口大于1时,可以在窗口范围内乱序接收分组,对于每一个接收的分组都会发送单独的确认报文,即我只确认收到了这个分组,这个分组之前的分组是否收到我不确定。
-
-
接收窗口的滑动
- 低序号分组到来,接收窗口移动
- 高序号分组到来,缓存但不交付,不滑动
-
-
-
回退N步GBN协议的异常处理
-
如果出现丢失或者超时时,发送方发送方重传所有已发送但是还未被确认的分组。而接收方如果接收到了失序的分组,则会直接丢弃,并响应当前已接受的最大的分组序号。
-
-
选择重传SR协议中的异常处理
- 当发送方接收到乱序的分组ACK时,发送窗口的后沿不会向前移动,直到超时重发机制让超时的分组重新发送出去
- 当接收方收到分组时,如果不再接收缓冲区的范围内,则丢弃分组,如果在范围内,但是是乱序的,接收该分组,并产生ACK,即使该分组已经被接收
-
回退N步协议与选择重传协议的对比
- 相同之处:发送窗口>1,一次能够发送多个未经确认的分组
- 不同之处
- GBN协议窗口尺寸=1,接收端只能顺序接收,发送端如果某一个分组发送失败,那就要回到这个分组重新开始发送之后所有的未确认分组。
- SR协议窗口尺寸>1,接收端可以乱序接收,发送端可以选择性的重发某一个失败的分组。
-
流水写协议总结
-
Go-Back-N,GBN协议
-
发送端最多在流水线中有N个未确认的分组
-
接收端只是发送累计型确认。接收端如果发现新来的分组与已接收的分组有间隙,那么就不会接收。
-
发送端拥有对最老的未确认分组的定时器
GBN协议只需要一个定时器。
当定时器到时时,重传所有未确认的分组
-
FSM
当上层
rdt_send(data)
时,当nextseqnum落在可发送的范围之内(base+N,N表示缓冲区大小),则形成一个新的分组,分组序号为nextseqnum,否则这个分组将无法被发送。如果
base=nextseqnum
,那就意味着在发送这个分组之前的所有分组都是已经确认的,就要开启定时器,并将序号加1。如果定时器超时timeout
,那么就要重传所有的未确认分组,并重新计时。当发送方成功收到ACK时,发送窗口的后沿需要向前移动,即
base=getacknum(rcvpkt)+1
,如果后沿base=前沿nextseqnum,那么就关闭定时器,因为此时没有待确认的分组,否则就重新计时。接收方接收到分组时,如果分组正确,并且是期望的分组
hasseqnum(rcvpkt,expectedseqnum)
,那么就解封装,传输data,响应ACK,并将期望分组的序号加1。如果接收到乱序的分组,就对顺序接收的最高序号的分组进行确认sndpkt=make_pkt(0,ack,checksum)
,并且乱序的分组将会被丢弃。
-
-
Selective Repeat,SR协议
-
发送端最多在流水线中有N个未确认的分组
-
接收方对每个到来的分组单独确认
-
发送方为每个未确认的分组保持一个定时器
SR协议需要多个定时器。当定时器到时时,重发到时的未确认分组。
-
-
-
两种协议的适用范围
- 链路出错率比较低:适合GBN
- 链路容量大,出错率高(延迟大):适合SR
-
5.面向连接的传输:TCP
-
TCP概述
- 面向连接:在一个应用程序可以开始向另外一个应用程序发送数据之前,这两个进程必须先相互“握手”
- 点对点:单个发送方与单个接收方之间的连接
- 三次握手:TCP连接建立的过程
- 最大报文段长度(Maximum Segment Size,MSS):取决于最大传输单元(Maximum Transmission Unit,MTU)
- TCP报文段:TCP首部+MSS
- 全双工数据:在同一连接中数据双向流动
- 发送和接收缓存:
-
TCP报文段
-
字节序号:TCP数据分为长度为MSS的若干块,字节序号就是每个报文段的字节偏移量,假设第一个报文段的字节序号为
x
,那么第二个就是x+MSS
,以此类推。为什么序号不是从0或者1这种固定序号开始的?
为了防止滞留在网络中分组被新的TCP连接上。
-
确认号:报文段的确认号是主机期望收到的下一字节的序号。比如主机A已经收到了主机B的编号0-9的所有字节,主机A等待的是10以及之后的字节,那么确认号就是10。
累计确认:如果收到确认号为10的报文段,那么说明小于该确认号的所有字节都已经被接受
-
-
TCP往返延时(RTT)和超时
-
合理的设置TCP超时时间的重要性
- 比RTT要长:但是RTT是变化的
- 太短:太早超时,产生不必要的重传
- 太长:对报文段丢失反应太慢
-
如何估计RTT与设置超时时间
-
SampleRTT-样本RTT的测量:从某段报文被发出到对改报文段的确认被收到之间的时间。大多数TCP仅在某个时刻做一次RTT测量。重传不计算
-
SampleRTT会随着路由器的拥塞和端系统的负载进行变化,直接使用SampleRTT是不行的,TCP会维持一个SampleRTT的均值:EstimatedRTT,每得到一个新的SampleRTT时,会通过以下公式更新EstimatedRTT。
当前时间的采样值对均值的共享最大,时间越往前的采样值对平均值的贡献越小。
α的推荐值:0.125
-
测量RTT的变化,估算SampleRTT一般会偏离EstimatedRTT的程度:
β推荐值:0.25
-
超时时间:
TimeoutInterval = EstimatedRTT+4*DevRTT
-
-
-
TCP是如何实现可靠数据传输的
-
TCP在IP不可靠服务的基础上建立了RDT
- 管道化的报文段,类似GBN协议或者SR协议
- 累计确认(GBN)
- 单个重传定时器
- 触发重传的机制:
- 超时(只重发最早的未确认报文段,类似SR协议)
- 收到冗余的ACK
-
简化版TCP
-
忽略重复的确认,忽略流量控制和拥塞控制
-
FSM:
当TCP连接建立之后,两边会确认一个发送的初始序号
InitialSeqNum
,当接受上层的数据时,创建报文段,并将报文段序号置为当前要发送的序号,更新NextSeqNum(滑动窗口的前沿向前滑动,已发送未确认),NextSeqNum=NextSeqNum+length(data)
,启动定时器。如果超时,则重传最小序号的未确认段,重新计时。当接收到ACK时,SendBase更新到ACK确认号的序号位置(滑动窗口的后沿向前滑动,确认的段),如果当前存在未确认报文段,则计时,否则关闭计时器。
-
-
TCP:超时间隔加倍
- 每当超时事件发生时,TCP未确认的最小序号报文段将会被重传,每次TCP重传时,都会讲下一次的超时时间设为原来的两倍,而不是通过EstimatedRTT和DevRTT计算得到。
- 这种修改提供了一个形式受限的拥塞控制。定时器过期可能是由于网络拥塞引起的,如果在拥塞的时候还在不断的重传分组,可能会使拥塞更加严重。
-
TCP:快速重传
- 当TCP收到冗余ACK,即再次确认某个报文的ACK,而发送方之前已经接收过此ACK,当收到冗余ACK的次数达到3次时,TCP就会执行快速重传,在该报文段的定时器过期之前就重传丢失的报文。
-
TCP:流量控制
-
TCP为它的应用程序提供了流量控制服务,以消除发送方使接收方缓存溢出的可能性。流量控制是一个速度匹配服务,即发送方的发送速率与接受方的应用程序读取速率相匹配。
-
TCP通过让发送方维护一个接收窗口的变量来提供流量控制。
假设主机A通过TCP连接向主机B发送文件,主机B为该连接分配了一个接收缓存:RcvBuffer
主机B从缓存中读取数据:
LastByteRead:主机B上的应用进程从缓存中读取的最后一个字节的编号
LastByteRcvd:放入主机B缓存中的最后一个字节的编号
由于TCP不允许已分配的缓存溢出,所以:
LastByteRcvd - LastByteRead <= RcvBuffer
接收窗口rwnd = RcvBuffer - [LastByteRcvd - LastByteRead]
主机B通过把当前的rwnd的值放入它发给主机A的报文段接收窗口字段中,通知主机A还有多少可用空间
-
-
TCP:连接管理
-
TCP连接建立,即双方知道对方要和我通信,并为此次连接做好准备工作
-
三次握手(Three-Way Handshake):
- 客户端的TCP首先向服务器的TCP发送一个特殊的TCP报文段。该报文段不含应用层数据,在报文段首部有一个标志位置为1(SYN=1,seq=client_isn),并随机选择一个**初始序号(client_isn)**放在TCP SYN报文段中
- 服务器从提取TCP SYN报文段,为该TCP连接分配缓存和变量,选择服务端的初始序号(server_isn),并响应一个允许连接的报文段SYNACK段(SYN=1,ack=client_isn+1,seq=server_isn)
- 客户端收到SYNACK报文段之后,也要为该TCP连接分配缓存和变量,并发送一个确认的报文段(SYN=0,seq=client_isn+1,ack=server_isn+1)
两次握手可以吗?
不行。
场景一:客户端A像服务器B发送建立连接请求,服务器B接受到之后,连接建立,但在响应客户端A时超时了,此时客户端A重新发送建立连接请求。随后,之前的服务器B响应报文被客户端A接受,客户端A建立连接成功。此次连接在客户端A第二次建立连接请求达到之前结束了,但是,第二次的客户端A连接建立请求被服务器B成功接受,服务器为客户端A建立了连接。此时,服务器端就维护了一个连接,但是客户端并没有维护连接,服务器凭空浪费了资源。
场景二:即服务器端不仅维护了半连接,同时还把老数据当成新数据进行接收。
-
TCP连接的释放(四次挥手):
TCP连接中的任意一个进程都可以终止该连接
- 客户端向服务器发出关闭连接的命令(标志位FIN=1,seq=x),服务器发送确认报文段(ack=x+1,标志位ACK=1)
- 服务器发送自己的终止报文段(FIN=1,seq=y),客户端发送确认报文段(ACK=1,ack=y+1)
- 在经过定时的等待之后,连接就被释放了
-
TCP状态
-
-
-
拥塞控制
-
拥塞的原因
- 网络中存在瓶颈,该瓶颈的吞吐量小于节点单位时间发送的数据量
- 接受缓冲区大于瓶颈处可用缓冲区
-
拥塞的代价
- 当分组的达到速率接近链路容量时,分组的排队时延将十分巨大
- 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组
- 发送方在遇到大时延所进行的不必要的重传(超时重传)会引起路由器利用其链路带宽来转发不必要的分组
- 当一个分组沿一条路径被丢弃时,每个上游路由器用于转发该分组使用的传输容量被浪费掉了
-
拥塞控制的方法
- 端到端的拥塞控制:网络层不为运输层提供拥塞控制的显式支持,而是由端系统自己对网络行为的观察来进行拥塞控制(TCP使用的方法)
- 网络辅助的拥塞控制:路由器向发送方提供关于网络中拥塞状态的显示反馈信息(ATM 可用比特率)
-
TCP拥塞控制
TCP拥塞的几个问题?
- 如何检测网络拥塞
- 控制策略:拥塞发生时如何降低发送速率,拥塞缓解时如何增加速率
-
拥塞感知
-
如果TCP出现“丢包”事件(超时或者受到3个冗余ACK),那么发送发就认为在链路上出现了拥塞的指示。
超时:
TCP出现超时重传可能是因为分组丢失,也可能是因为分组出错被丢弃了,后者出现的概率比前者小得多,所以在出现超时的事件后,发送方就认为链路上发生了拥塞
3个冗余ACK:
如果发送方收到3个冗余ACK,说明链路上出现了一定程度的拥塞,可以看做轻微拥塞,拥塞程度比第一种轻
-
-
控制发送端发送的速率:
-
维持一个拥塞窗口的值:CongWin
-
发送端限制已发送但是未确认数据量的上线即:
LastByteSent - LastByteAcked <= CongWin
-
从而粗略的控制发送方往网络中注入的速率:
rate = CongWin/RTT
bytes/sec
-
-
TCP拥塞控制算法
-
慢启动:在TCP刚连接时,CongWin = 1 MSS,每当传输的报文段被首次确认就增加1个MSS,第一次1个,第二次2个,第三次4个…,随着发送报文的不断增长,一定会发生拥塞。当发生超时事件时,将慢启动阈值设置为CongWin/2,并将CongWin重置为1,并重新开始慢启动。当后续的CongWin达到或超过慢启动阈值时,TCP结束慢启动阶段。开始进入拥塞避免模式。
-
拥塞避免:进入拥塞避免后,TCP的发送速率采用一种较为保守的方法,每个RTT将会只增加1个MSS(TCP可以在1个RTT内发送多个报文段)。当发生超时事件时,处理方式与慢启动阶段相同。当发生3个冗余ACK时,慢启动阈值变为CongWin/2,CongWin = CongWin/2 + 3,并进入快速恢复阶段。
-
快速恢复:TCP每收到一个冗余ACK,CongWin值加1个MSS
-
TCP拥塞控制常常被称为加性增、乘性减拥塞控制方式
-
FSM:
-
-
TCP吞吐量
- TCP发送数据的速率是拥塞窗口与当前RTT的函数,忽略慢启动的时间(慢启动的时间很短)
- 假设窗口大小为w,当前往返时间为RTT秒,那么TCP的发送速率=w/RTT
- TCP每经过一个RTT将增加一个MSS,直到第一个丢包事件发生,所以TCP的传输速率在w/2*RTT ~w/RTT 之间
- 一条连接的平均吞吐量=0.75*w/RTT
-
TCP的公平性
-
假设有两个TCP连接共享带宽为R的链路,忽略TCP的慢启动阶段,假设TCP一直处在拥塞避免阶段,并且RTT时间相同
-
某时刻,两个TCP连接形成了A点所在的吞吐量,因为两条连接的吞吐量总和小于链路带宽时,并且处于拥塞避免阶段,所以每经过一个RTT,A点就会沿45°方向前行,当两条连接的总吞吐量大于链路带宽时,会出现丢包事件,两条连接的窗口都会缩减1/2(x轴,y轴各1/2),就变成了C点所在的位置,重复上述操作,两条连接实现的带宽最终将沿着平等带宽共享曲线波动。
公平性和UDP:
UDP没有拥塞控制,也不会降低自己的发送速率,所以当TCP和UDP一起时,UDP会不断压制TCP的流量。
公平性和并行TCP连接:
多个并行连接的TCP相比较单个TCP连接会占用更多的带宽。
-
-