运输层
运输层
运输层协议
-
进程之间的通信
-
运输层的复用和分用
应用层所有应用进程都可以通过运输层再传送到IP层;
运输层从IP层收到发送给各个应用进程的数据后,必须分别交付指明的各应用进程。
-
面向连接的TCP和无连接的UDP
-
TCP报文段和UDP用户数据报
-
运输层的端口
用一种统一的方法标记本计算机应用层的各个进程和运输层交互的层间接口。
-
服务端使用的端口号(熟知端口号&登记端口号)和客户端使用的端口号(短暂端口号)
TCP
传输控制协议TCP
- TCP是面向连接的传输层协议(应用程序使用TCP协议之前需要建立TCP连接。传送数据完毕后,必须释放已经建立的TCP连接)
- 点对点连接
- 可靠交付(无差错、不丢失、不重复、按序到达)
- 全双工通信(允许通信双方的应用进程在任何时候都能发送数据)
- 发送缓存&接收缓存
- 面向字节流(TCP把应用程序交下来的数据仅仅看做一串无结构的字节流)
TCP报文段先要传送到IP层,加上IP首部以后,再传送到数据链路层,再加上首部和尾部以后,才离开主机发送到物理链路。TCP并不关心应用进程一次把多长的报文发送到TCP缓存中,而是根据接收方给出的窗口值和当前网络的拥塞程度再来决定一个报文段应该包含多少字节。
TCP的连接
- 每一条TCP连接两个端点(这个端点不是IP地址,不是应用进程,也不是运输层的协议端口),端点叫套接字socket或者插口。
- 套接字socket=(IP地址:端口号)
可靠传输的工作原理
(理想传输条件:传输信道不产生差错&不管发送方以多快的速度发送数据,接收方总是来的及处理收到的数据)而网络层提供的是不可靠的传输
,传输层就要使用一些可靠传输协议:当出现差错时可以让发送方重传出现差错的数据;同时在接收方来不及处理收到的数据时,即时告知发送方适当降低发送数据的速度。
-
停止等待协议(学习概念思想就好,运输层并不使用这种协议)
-
无差错情况
-
出现差错
-
确认丢失和确认迟到
超时重传、超时计时器、编号(适用这种确认和重传机制,就可以在不可靠的传输网络上实现可靠的通信)
简单,但是信道利用率太低,可以采用流水线传输。
-
-
连续ARQ协议(累积确认,接收方对按序到达的最后一个分组发送确认,回退N)
-
滑动窗口协议(TCP传输控制协议的精髓)
TCP报文段的首部格式
TCP固定首部20字节,选项部分最长40字节。
- 源端口&目的端口(各2字节)
- 序号(4字节):本报文段所发送数据的第一个字节的序号。TCP连接传送的每一个字节都按顺序编号。
- 确认号(4字节):期望收到对方下一个报文段的第一个数据字节的序号。也就是如果确认号是N,表明N-1之前的所有数据都已经正确收到。
- 数据偏移(4位):单位是32位字(4字节);实际上支持的是TCP报文段的首部长度,侧面表达了TCP首部的最大长度是60字节。
- 保留(6位)
- 6位控制位:用来说明本报文段的性质
- 紧急URG
- 确认ACK:ACK=1时确认号字段才有效;TCP规定,连接建立之后所有传送的报文段都必须ACK=1。
- 推送PSH
- 复位RST
- 同步SYN:连接建立时用来同步序号,SYN=1时表示这是一个连接请求或者连接接收报文。SYN=1&ACK=0(连接请求),SYN=1&ACK=1(连接接受)。
- 终止FIN:FIN=1,表明此报文段发送方数据已经发送完毕,要求释放运输连接。
- 窗口(2字节):以字节为单位,指发送本报文段一方的接收窗口,因为接收方的缓存空间是有限制的,所以要明确指出现在允许发送方发送的数据量,窗口值动态变化,作为发送方设置发送窗口的依据。
- 检验和(2字节):TCP报文段前面加上12字节的伪首部计算检验和,检测范围包括首部和数据两部分。
- 紧急指针(2字节):在URG=1时有意义,指出本报文段中紧急数据的字节数,紧急数据结束以后就是普通数据。接收方处理紧急数据时会进入紧急状态,当所有紧急数据处理完后,TCP告诉应用进程恢复到正常操作。即使窗口值为零也可以发送紧急数据。
- 选项(长度可变,需要对齐填充保证TCP报文段首部是4字节的整数倍):
- 最大报文长度
- 选择确认
- 窗口扩大
- 时间戳
- ……
TCP可靠传输的实现
-
以字节为单位的滑动窗口
-
已经发送但未收到确认的数据均需保存副本。
-
发送窗口不能超过接收窗口数值,发送窗口同时也会受到网络拥塞程度的制约。
-
接收窗口只能对按序收到的数据中的最高序号给出确认(累积确认,减少传输开销;选择确认,减少不必要的重传);对不按序到达的数据临时存放在接收窗口,等待字节流中所缺少的字节收到后才按序交付给应用进程。
-
为了保证可靠传输,发送只能认为接收方可能没有收到数据,会在超时计时器的控制下重传数据,直到收到确认。
TCP的通信是全双工通信,通信的每一方都在发送和接收报文段,因此每方都有自己的发送窗口和接收窗口。
-
-
超时重传时间的选择
重传时间是TCP最复杂的问题之一。采用了一种自适应算法:是一个比加权平均往返时间RTTs略大的超时重传时间RTO。
-
选择确认SACK
选择确认是一种能做到只传送缺少的数据,而不重传已经正确到达接收方的数据的可行方法。
如果收到数据的字节的序号都在接收窗口之内,那么接收方就先收下这些数据,但是要把这些信息准确告诉发送方,使发送方不再重传已经收到的数据。而TCP首部选项中就可以提供关于已经收到的字节块的序号边界信息,在接收方和发送方事先商定的情况下,如果要使用选择确认SACK,那在建立TCP连接时,就在TCP首部选项中加上“允许SACK“的选项,由于选项部分长度最多40个字节,之后选项中最多会包含4个字节快的边界信息,和一个指明是SACK的选项的字节,以及一个字节指明这个选项占用多少字节。
但是SACK文档中并没有指明发送方应该怎么响应SACK,所以大多数的实现还是重传未被确认的数据块。
TCP的流量控制
发送方发送速率不要太快,要让接收方来的及接收。
-
利用滑动窗口实现流量控制(利用可变窗口进行流量控制)
TCP窗口的单位是字节,不是报文段,接收窗口rwnd,字节序号seq,确认位ACK,确认号ack。
如果接收方进行流量控制,将窗口值减小到0后,发送方暂停的状态会持续到接收方重新发送一个新的窗口值为止,而为了防止这个包含新的窗口值的报文段丢失,造成发送方接收方互相等待的死锁状况,TCP为每一个连接都设置了一个持续计时器,只要TCP连接一方接收到对方的零窗口通知,就启动持续计时器,时间到期向接收方发送一个零窗口探测报文,这时接收方会返回现在的窗口值,打破死锁僵局。
-
TCP传输效率
如何控制TCP发送报文段的时机是一个较复杂的问题。
-
糊涂窗口综合征
糊涂窗口综合症是指当发送端应用进程产生数据很慢、或接收端应用进程处理接收缓冲区数据很慢,或二者兼而有之;就会使应用进程间传送的报文段很小,特别是有效载荷很小; 极端情况下,有效载荷可能只有1个字节;传输开销有40字节(20字节的IP头+20字节的TCP头) 这种现象。
发送方和接收方都可能会引发糊涂窗口综合征。
-
接收方
接收方进程处理缓存中的数据不及时,一旦腾出一点缓存空间又然后通知一个较小的窗口给发送方;然后发送方会按照这个窗口值发一段较短的数据,循环往复。所以对于接收方应该避免通知较小的窗口值,可以使用延迟确认的方式等缓存中的数据被清空或者有足够的空间,再告知窗口值。
-
发送方
发送方产生的数据比较慢,每次产生的数据都很小。对于发送方不应该发送小的报文段,可以使用Nagle算法来控制何时发送,可以把数据积累成足够大的报文段,或者是达到接收方缓存空间的一半大小。
-
-
Nagle算法
Nagle算法是一种拥塞控制算法。每次发送少量的数据时,TCP的首部和IP的首部会有很大的开销,这会造成相当高的网络传输代价(这种代价对局域网没有影响,对广域网可能造成拥塞,如糊涂窗口综合征),Nagle算法就是用来解决这种小包可能导致网络拥塞的问题。(解决的问题)
Nagle算法要求,当一个TCP连接中有在传数据(已经发送但还未经确认),小的报文段(长度小于SMSS,SMSS是指发送方能够发送的最大数据段的长度)就不能被发送,直到所有的在传数据都收到ACK,TCP会将小数据收集整合到一个报文段中发送。大的报文段不受Nagle算法的影响,实际上Nagle算法对于小的报文段来说就是一个停止等待协议。(Nagle算法原理)
因为要等到所有在传数据收到ACK才发小数据,那么ACK返回的越快,小数据包传输也就越快,如果是时延比较高的广域网中,ACK返回就会越慢,小数据被发送出去的速度也会变慢,这样小数据包就不会加重网络的阻塞。也就是说RTT可以控制发包速率。(Nagle算法为什么有效)
累积确认与Nagle算法直接结合使用效果会很差,延迟确认会使得接收方推迟发送ACK报文,而使用了Nagle算法的发送方又要等到接收到ACK报文才发送,导致网络处于空闲状态。(延时ACK与Nagle算法)
要求时延尽量小的应用不适合使用Nagle算法如网络游戏,远程控制等。(Nagle不适合的场景)
-
TCP的拥塞控制
-
拥塞控制的一般原理
- 对网络资源的需求超过了它所能提供的可用部分,路由器因无法处理高速率到达的流量而被迫丢弃数据信息,网络性能变坏,这种情况就叫拥塞。
- 网络拥塞往往由许多因素引起,比如某个结点缓存容量太小、处理机处理速率太慢等等。但是如果仅仅改善其中某一个方面,又会把瓶颈引向其他地方,所以问题的实质往往是整个系统的各个部分不匹配,需要把各个部分平衡了才能解决问题。
- 拥塞控制&流量控制:拥塞控制是防止过多数据注入到网络中使得路由器或者链路过载,以网络承受的符合为前提,是一个全局性的过程;而流量控制往往指点对点通信量的控制,是个端到端的问题。
- 拥塞状态&拥塞控制:轻度拥塞、拥塞状态;开环控制、闭环控制;检测网络拥塞
-
TCP的拥塞控制方法
拥塞窗口取决于网络的拥塞程度,而只要网络没有出现拥塞,拥塞窗口就可以增大一些,以提高网络利用率;相反就要减小拥塞窗口,减少注入网络的分组数目,缓解拥塞。
拥塞窗口以报文段个数为单位。
-
慢开始和拥塞避免
慢开始:主机开始发送数据时先探测网络情况,由小到大地增大发送窗口。拥塞窗口没有到达慢开始门限值的时候每收到一个确认报文段就把拥塞窗口的值加一,是一个指数增长的特点;而如果到达了慢开始门限值后就开始采用拥塞避免算法,拥塞窗口的大小开始按线性增长,增长速率会缓慢很多,使网络不容易出现拥塞。当出现超时以后,发送方判断是出现了网络拥塞,会重新设置拥塞窗口大小,再从慢开始逐渐增大窗口值,慢开始门限值会设置的比之前要小。
但是当传送数据丢失也会引起超时,这时不是网络拥塞的情况,如果发送方因此判断拥塞而重置拥塞窗口,会降低传输速率。所以需要使用快重传,然后发送方尽早了解个别报文段的丢失。
-
快重传和快恢复
快重传要求接收方对收到的数据立即发送确认,即使收到失序的报文段也要立即发出对已经收到的报文段的重复确认。快重传算法规定,发送方只要一连收到三个重复确认,就知道接收方确实没有收到某个报文段,会立即进行重传(快重传),发送方也不会因此判断错误认为出现网络拥塞,大大提高网络吞吐量。所以当出现丢失后,不再启动慢开始,而是执行快恢复算法,调整慢开始门限值为拥塞窗口的一半大小(乘法减小),然后拥塞窗口也减小为门限值的大小,开始执行拥塞避免算法。
-
-
主动队列管理AQM
路由器的队列通常按照“先进先出”的处理规则处理到来的分组,但是队列长度总是有限的,因此队列满了以后到达的分组会被丢弃,这是一种尾部丢弃策略。但是路由器的尾部丢弃会导致一连串分组的丢失,就使发送方出现超时重传,使得TCP进入拥塞控制的慢开始状态,结果使TCP连接的发送方突然把数据发送速率降低到很小的数值。甚至还会因为TCP报文段复用网络层IP数据报而影响到很多条TCP连接,使得这些TCP连接同一时间突然进入到慢开始状态的全局同步现象。
为了避免这种现象,提出了通过主动队列管理AQM对路由器中的分组队列进行智能管理,而不是简单丢失掉队列尾部的数据。“主动”就是不等到已经发生了网络拥塞后才将所有队列尾部的分组丢弃,而是在检测到网络拥塞的早期征兆时就以概率p丢弃个别分组,以提醒发送方放慢发送速率,减轻网络拥塞的程度,或让拥塞控制只在个别的TCP连接上进行,避免全局性的拥塞控制。
TCP的运输连接管理
TCP面向连接,在运输层传输TCP报文段,连接中有三个阶段:连接建立、数据传送、连接释放。
TCP连接建立的过程需要思考的是:如何让每一方都确知对方存在;并且在这个阶段可以双方协商一些参数(最大窗口值、是否使用窗口扩大、是否使用时间戳等);对运输实体资源进行分配。
-
TCP连接建立
三次握手
-
传输报文ACK、SYN、seq、ack
-
双方的几种不同状态
-
四报文握手的情况
-
理解为什么发送方还要进行第三次握手。
-
-
TCP连接释放
四次挥手
- 传输报文FIN、ACK、seq、ack
- 双方的几种不同状态
- 时间等待计时器,理解客户端设置的2MSL的作用。
保活计时器:保证客户端服务端建立连接以后客户端主机出现故障后,服务器能够不一直等待下去而关闭连接。服务器每收到一次客户端数据,就设置一个保活计时器,时间设置通常是两小时,如果两小时以后没有收到客户端的数据,就发送探测报文段,之后每隔75s发送一次,若发送十次都没有响应,就认为客户端出了故障,可以断开。
-
TCP的有限状态机
关于TCP连接当中的各种状态
三次握手四次挥手的画图
UDP
UDP
UDP用户数据报只在IP的数据报服务之上增加了复用和分用以及差错检测的功能。
关于UDP的特点:
- 无连接:发送数据不需要建立连接,因此也减少了开销和发送数据之前的时延。
- 尽最大努力交付:主机因此不需要维护复杂的连接状态了。但一些使用UDP的实时应用,也会对UDP的不可靠数据传输适当改进,减少数据丢失。
- 面向报文:作为发送方,UDP对于应用层交下来的报文,既不合并也不拆分,会保留这些报文的边界照样发送不做变动;而作为接收方,UDP对IP层交上的UDP用户数据报,在去除首部以后就原封不动地交付给上层的应用进程。
- 没有拥塞控制:因此网络的拥塞不会使源主机的发送速率降低,对于某些实时应用,这一点非常重要。但是当很多源主机都向网络中发送高速率的实时数据时,不使用拥塞控制的UDP可能会引发严重的网络拥塞问题。
- 支持一对一、一对多、多对多、多对一的交互通信。
- 首部开销小。:比起TCP的20个字节的固定首部,UDP首部只有8个字节。
UDP首部格式
首部字段+数据字段
-
首部(每个字段长度2字节)
- 源端口:不需要对方回信可以全用0。
- 目的端口:终点交付报文必须使用。
- 长度:UDP用户数据报的长度,最小为仅有首部长度为8的情况。
- 检验和:检测UDP用户数据报在传输过程中是否有错,有错丢弃。
-
数据
-
关于UDP用户数据报的检验和计算。
UDP的检验和是把首部和数据部分一起检验,检验和的计算需要在UDP用户数据报之前加上12字节的伪首部构成一个临时的UDP用户数据报,检验和会根据这个临时的UDP用户数据报来计算。
伪首部包含的内容:源IP地址(4字节)、目的IP地址(4)、全零(1)、IP首部中的协议字段的值对于UDP就是17(1)、UDP用户数据报的长度(2)。
发送方会将UDP用户数据报的数据部分填入全零字节凑成偶数个字节,然后按照二进制反码计算出每16位字的和,将这个和的二进制反码写入检验和字段,就发送这样的UDP用户数据报。接收方会把收到的UDP用户数据报连同伪首部及可能的填充字节一起,按照二进制反码求这些16位字的和,当无差错其结果应该为1,有差错则丢弃,或者附上差错警告交付上层。
这种简单的差错检验方法检错能力不强,胜在简单,处理起来较快。