文章目录
TCP协议和可靠传输的工作原理。tcp的三个重要问题:滑动窗口、流量控制、拥塞控制机制。
通过本章可以学习。
- 运输层为相互通信的应用进程提供逻辑通信
- 端口和套接字的意义
- 无连接的UDP的特点
- 面向连接的TCP的特点
- 在不可靠的网络上实现可靠传输的工作原理,停止等待协议和ARQ协议
- TCP的滑动窗口、流量控制、拥塞控制和连接管理
一、运输层协议概述
小冯:有了IP协议为什么还需要运输层?
计算机网络:网络层是为主机之间提供逻辑通信,而运输层为应用进程之间提供端到端的逻辑通信。如图1所示。
UDP是无连接的,不可靠的;而TCP是面向连接的,可靠的传输。因为TCP是可靠的传输,不可避免的就要使数据单元的首部增大了。TCP为什么如此重要。可以从下图中看出。
由图2可以看出,重要的应用层应用层协议HTTP、电子邮件、远程终端、文件传输都是运输层的TCP实现的。
运输层的复用与分用。
假定一个机构的所有部门向外发送邮件,都先发送给收发室,这相当于各部门复用收发室。当收发室从外单位收到邮件后,将邮件分发给公司各部门,这相当于各部门分用该收发室。
运输层也是这样的。虽然通信的终点是应用进程,但是只要把传输的报文交给目的主机的目的端口就行,然后由TCP协议完成将端口中收到的报文交给应用进程。
二、用户数据报协议UDP
UDP一次交付一个完整的报文,不管应用层传下来的报文有多长。总之,应用层传递下来的报文要合适,过长(IP层会分片),过短(IP数据报首部相对长度太大)都会影响IP层的效率。
UDP的特定是:
- 无连接
- 尽最大努力交付
- 面向报文的。一次交付一个完整的报文
- 没有拥塞控制。意味着发送方的发送速率不会降低,对于很多实时系统是可行的(保证实时就行了,丢失一些数据是允许的)。然而,当有很多发送方向网络发送数据时,会造成严重的网络拥塞,进而每个接收方都收不到数据,从而都播放不了视频。
- UDP支持一对一、一对多、多对多、多对一的交互通信(2X2)
- UDP的首部开销小。相对于TCP的可靠传输而言,是这样的。
UPD数据报的首部与伪首部如图3所示。
伪首部只是用来计算校验和的,它既不往下传送,也不向上递交,只是用来计算校验和的。
三、传输控制协议TCP概述
TCP连接的主要特点。
- TCP是面向连接的运输层协议。
- 一对一通信。就像打电话一样。
- TCP听可靠传输。通过TCP接受的数据,无差错、不丢失、不重复、按序到达。
- 面向字节流。应用层发送给TCP多少个数据库,并不意味着接受放的TCP交给应用层就有多少个数据库。这是因为TCP连接的两端设有发送缓存和接收缓存。
TCP面向流的示意图如图4所示。
TCP一次发送多少数据给IP层并不由应用层发送下来的数据觉得,而是有接收方给出的窗口值和当前网络拥塞程度决定。
四、可靠传输的工作原理
由于IP网络层提供的是不可靠的传输,所以TCP需要提供可靠的传输。TCP提供可靠传输需要解决下面两个问题。
- 当发送的数据发生差错时,需要重传数据。
- 当接受放处理不过来数据时,要降低发送方的发送速率。
4.1 停止等待协议
停止等待协议是计算机网络发展早起,网络不可靠,数据链路层提供的一种可靠传输。不是运输层的。它的精髓所在是,当A发送玩一个分组M1之后,需要等待B发送确认消息之后,才继续发送分组M2。示意图如图5所示。
这里重传是自动的,发送方超过时间都还没有接受到接收方的确认信息,就自动重传。这就是自动重传请求ARQ(automatic repeat reQuest)
停止等待协议的优点就是简单。确定就是信道利用率太低。示意图如图6所示。
假设从一个分组开始从A发送到发送出去花了时间TD,然后分组在网络上传输的时间为RTT,接收方从发送确认信息开始到完全发送完确认信息花了时间TA。所以信道利用率为。
U=Td/(Td+RTT+Ta)
Ta一般远小于Td,而传输时延一般都是固定的,所以当发送速率越快时,行到利用率就越低。
为了提高信道利用率,可以采用流水线传输。流水线传输示意图如图7所示。
4.2 连续ARQ协议
连续ARQ协议示意图如图8所示。
图8 中(a)表示同一个窗口中的分组可以连续发送出去,只要发送方接受到一个确认,就把窗口向前移动一格。接收方一般采用的是累积确认,只返回连续收到的分组的最后一个分组的序号,这表示该分组前面的分组已经正确收到了,发送方的窗口就移动对应的几格子。
累积确认的优点就是,即使确认信息丢失了,也不用重新发送确认信息,只要该确认信息后面的确认信息被发送方收到,就表明了上一个分组的确认信息是发送了的,只不过发送方没收到而已。累积确认的确定就是不会向发送方发送完整的接收方已经收到的分组的所有信息。
五、TCP报文段的首部格式
TCP的全部功能都体现在它的首部中的各字段中,因此,弄清TCP首部各字段的作用才能掌握TCP的工作原理。
- 源端口和目的端口。我们都知道TCP会把IP层发送过来的分组交个应用层的对应进程。所以需要源端口和目的端口来告知是两个主机中哪两个进程在通信。
- 序号。TCP是面向字节流的。tcp传输的是一个有序的字节流,而序号记录了这一个字节流中第一个字节的序号。如一个报文段的序号为301,携带的字节流长度为100个字节,说明本报文段的第一个字节序号为301,最后一个了字节的序号为400。下一个报文段的数据序号从401开始。
- 确认号。当接受方接受到发送方发送的报文后,会发送一个报文段应该发送的报文的第一个字节的需要。也就是说接收方发送确认报文段中的确认好为701,说明发送方下一个报文段的第一个序号应该从701开始。
若确认好 = N,则表明,接受方正确接受到了N-1之前的所有数据
- 数据偏移。指出了TCP报文段的首部长度,也就是Tcp报文数据部分离tcp报文的首部起始处的距离。
- 保留。占6位,用来以后使用。
- 紧急URG。说明此报文段中有紧急数据,应尽快传送,而不按原来的排队顺序来传送报文。比如使用远程连接,在远程主机上运行一个程序,突然发现了严重问题,需要终止程序,使用Ctrl+c。如果不使用紧急数据,那么ctrl+c会存在tcp缓存的末尾,直到ctrl+c以前的数据被处理完后,才执行ctrl+c命令。URG需要配合紧急指针使用,用来告诉接收方,本报文段中紧急数据的长度。
- 确认ACK。当连接建立之后,所有传送的报文段都应该把ack置为1。
- 推送PSH。当两个进程在进行交互式通信时,需要发送放在发送一个命令之后,立即收到接收方的相应。就需要用这个,这样,就不用等待接受方的tcp的接受缓存填满之后,才将数据递交给应用进程(与紧急URG的区别是,紧急URG是改变紧急报文和普通报文的发送顺序,而PSH是应该也是被标记为PSH的报文立即发送,接受方不用等待接收缓存满后,才递交数据给应用进程)
- 复位RST。当rst=1时,表示tcp连接中发生了严重差错,必须释放连接,然后在重新建立运输连接。常用来拒绝一个非法的报文段或拒绝打开一个连接。
- 同步SYN。在建立连接时需要用到。当syn=1并且ack=0,表明这是一个连接请求报文段。若对方同意建立连接,在应返回syn=1,ack=1的响应报文。
- 终止FIN。用来释放一个连接。当FIN = 1时,表明此报文段的发送方的数据已经发送完毕,并请求释放运输连接。
- 窗口。发送方发送报文段的接受方的接受窗口。用来告诉发送方,接收方目前允许发送方发送的数据量(因为接收方的数据缓存空间有限)。
- 校验和。和UDP的校验和类似,需要添加一个伪首部用来校验首部和数据部分。
- 紧急指针。用来告诉接收方,本报文段中紧急数据的长度。
- 选项。最大报文段长度MSS是用来避免ip层传输数据时分片传输。窗口扩大是用来扩大窗口的。时间戳可以用来计算往返时间RTT和防止序号绕回PAWS。
今天,不经意间想到。直播应该用的是udp,比如新闻联播中,主持人常常要和新闻现场的记着做同步交流。因为这要保证实时性。由于tcp是无差错、不丢失,意思是我包丢了或错了,要重传,不会出现视频跳跃式前进的。而udp的发送方速率是不变的,是不可靠的,丢包就丢包,进而保证了实时性。
所以,总结,视频传输中,出现进度跳跃的,也就是跳过了一部分视频,使用的是udp。而不管视频播放有多卡,视频的每一帧都是被播放了的,使用的是tcp。
进而可以联想到,在玩lol时,有些时候跳帧,也就是玩着玩着突然卡了,然后等一段时间之后,画面才启动,此时游戏已经跳跃了一段时间了,这里在运输层用的应该也是udp。
这只是鄙人的一波看法,不知道对不对。希望大佬们看得之后,指定一下。?
六、TCP可靠传输的实现
6.1 以字节为单位的滑动窗口
P3 - P1:A的发送窗口(通知窗口)
P2 - P1:已发送但未收到确认的字节数。
P3 - P2:允许发送但尚未发送的字节数(可用窗口、有效窗口)
TCP的缓存和窗口的关系如图10 所示。
发送缓存用来暂时存放:
- 发送应用程序传送给发送方TCP准备发送的数据。
- TCP已发送但尚未收到确认的数据。
接受缓存用来暂时存放:
- 按序到达的、但尚未被接收应用程序读取的数据。
- 为按序到达的 数据。
tcp的发送方在规定的时间内没有收到确认就要重传已发送的报文段。
6.2 超时重传时间的选择
TCP采用了一种自适应算法。它采用以下公式计算超时重传时间。
RTO=RTTS+ 4xRTTd ------------------【公式5-5】
RTO:表示超时重传时间。
RTTS:报文段的往返时间RTT的加权平均值,也称为平滑的往返时间,S表示smoothed。很明显,超时重传时间应大于报文段的平滑往返时间。第一次的RTTS的大小就为RTT样本的时间,以后每增加一个RTT,RTTS的计算方法如下。
新的RTTs = (1-a) x (旧的RTTS) + a x (新的RTT样本)
a的大小推荐为1/8
RTTD:RTT的偏差的加权平均值。RTTD的计算方法如下。
新的RTTD = (1-b) x (旧的RTTD) + b x | RTTS - 新的RTT样本 |
b的推荐值为1/4
如果tcp的发送放在超时重传时间之后都没有收到报文确认,就会重传已经发送了的报文。可是问题来了。这次收到报文确认,是对先发送的报文段的确认,还是后来重传的报文的确认?。示意图如图11所示。
使用改善后的karn算符解决。报文段每重传一次,就把超时重传时间RTO增大一些,一般是变成原来的两倍。当不在发生报文段的重传时,采用公式5-5计算。
6.3 选择确认SACK
首先,引入一个问题:若收到的报文段无差错,只是为按序号,中间缺少一些数据,有没有办法将不重传这些数据。
答案是有的。那就是选择确认sack。选择确认的接受方将收到的这些 不连续的数据的信息要告知给发送方。
但是,???。由于sack文档中没有指明发送方应当如何响应sack。所以大多数的实现还是重传所有未被确认的数据块。
七、TCP的流量控制
7.1 利用滑动窗口实现流量控制
流量控制就是让发送方的发送速率不要太快,好让接收方来得及接受数据。流量控制的示意图如图11 所示。
tcp中进行流量控制是使用滑动窗口进行控制的。
tips!
图11 中ACK是tcp报文格式中的首部的确认位。而ack表示确认号的具体值。
当B向A发送的滑动窗口的值为0时,A就不会发送数据了,直到B重新发送一个非零的滑动窗口给A。这里需要提及一个问题——当B向A发送了一个为0的滑动窗口之后,A等待B发送一个 非零的滑动窗口,可是B发送的这个含有非零窗口的报文丢失了。这样A一直等待,并且B也等待A的确认报文,这样会发生死锁。这咋搞呢??
解决办法。当A收到一个为零的滑动窗口时,就启动一个持续计时器,如果超时,就发送一个零窗口探测报文段,然后只要B返回一个非0滑动窗口就解决了死锁局面;不然,A一直重新设置持续计时器。
7.2 传输效率
就是发送方不要发送太短的数据,接收方不要在缓存有了一小点空间时,就发送确认报文(仅含有很小的滑动窗口大小)给发送方。
八、TCP的拥塞控制
8.1 拥塞控制的原理
拥塞:当网络对某一种资源(带宽、交换机结点中的缓存和处理机)的需求大于了实际可用资源总和,这时就发生了拥塞。可用下面式子说明。
对需求的资源之和 > 可用的资源
网络拥塞控制是一个很复杂的问题,单纯的增加带宽、交换机结点的缓存或处理机非但不能解决拥塞,甚至为让网络性能下降。
拥塞控制和流量控制有相似之处,但也有区别。流量控制是端到端控制的,而拥塞控制是整个网络层面全局性的过程的。为什么会混淆拥塞控制和流量控制,是因为很多拥塞控制方法都是让发送方降低发送速率。
理想的拥塞控制、实际的拥塞控制、无拥塞控制的示意图如图12所示。
横坐标表示单位时间内发送给网络的分组数。纵坐标表示单位时间内从网络接收的分组数。当无拥塞控制是,当网络的负载达到某个值时,网络的吞吐量会急速下降,最后归零,这是就发生了死锁。
拥塞控制是一件不容易的事情。从大体来说,有两种方法。
- 开环控制。意思是在网络工作前,考虑到拥塞问题,力求网络工作中不会发生拥塞,当网络工作过程中,不允许改正。
- 闭环控制。闭环控制是基于反馈环路的概念。意思是在网络工作中,发生拥塞时,运行改正。
8.2 拥塞控制的常见方法
慢开始和拥塞避免
发送方维持了一个拥塞窗口,发送窗口的大小等于拥塞窗口。而实际上,发送窗口的大小可能小于拥塞窗口。下面图13是慢开始算符的示意图。
每经历一次传播轮次(其实就是往返实际RTT)拥塞窗口的大小就加倍。为了避免拥塞窗口过大造成网络拥塞,需要一个慢开始门限。当拥塞窗口大于慢开始门限,就使用 拥塞避免算法。慢开始算法,让拥塞窗口按线性增长(增长量为一个报文大小)。拥塞避免算法示意图如图14所示。
不论是在慢开始阶段,还是拥塞避免阶段,只要发送拥塞,就让慢开始门限大小减半,并让拥塞窗口从1开始,执行慢开始算法。
慢开始算法,并不能完全避免网络拥塞,只能使网络比较不容易出现拥塞。
快重传和快恢复
快重传,当接收方接收到一个失序的报文段后就立即发出重复确认,发送方只要接收到三个重复确认就立即重传接收方尚未收到的 报文段。快重传的示意图如图15 所示。
途中M3是丢失了的,当接收方收到了失序的M4,M5,M6时就发出重复确认报文,发送方就重传丢失的不保温M3。
与快重传配套的算符是快恢复算法,其示意图如图16 所示。
快恢复算法,当收到三个重复的确认,使用快重复算法发送丢失的报文,然后使用快恢复算法将慢开始门限减半,并让拥塞窗口的大小设置为慢开始门限的大小(不是1)。
8.3 随机早期检测RED
路由器的接受分组的队列大小是有限的,当分组放不下时,将使用尾部丢弃策略将最后到达的分组丢弃。然而,这样容易造成问题,由于ip层是复用的,以为着每个分组都可能来自不同的源点和终点,当把这些分组丢弃时,会使各发送方出现超时重传。这样每个源点都会降低发送速率,从而导致全网的通信量一下降低非常多,这就叫做全局同步。随机早期检测RED就是用来避免全局同步问题的。其示意图如图17所示。
当平均长度队列长度小于THmin时,丢弃报文的概率为0;
当平均长度队列长度大于THmin时,丢弃报文的概率为1;
当平均长度队列长度间于THmin与THmax时,丢弃报文的概率为p;
p是有一个计算公式的。
九、TCP的运输连接管理
9.1 tcp的连接建立
运输连接有三个阶段。
-
连接建立
-
数据传送
-
连接释放
tcp连接采用的是客户服务器方式。主动发起连接建立的应用进程叫做客户,而被动等待连接建立的应用进程叫做服务器。 -
B的tcp服务器进程先创建传输控制块TCB(传输控制块tcp存储了每一个连接中的一些重要信息,如:tcp连接表,到发送和接收缓存的指针等),装备接受客户进程的连接请求。然后服务器进程就处于listen状态,等待客户的连接请求。
这里需要提一下,为什么需要让A发送一次确认,是为了避免以下情况。
当A发出的第一个请求连接报文段并没有丢失,而是在某些节点长时间滞留了,以致于延误到连接释放以后的某个时间才到达B。本来这是一个早已失效的报文段。但B收到此失效的连接请求报文段后,就误以为是A又发出一次新的连接请求。于是就向A发出确认报文段,同意建立连接。
9.2 tcp的连接释放
tcp连接的释放采用的是四次握手原理。
在time-wait阶段,tcp连接还没有释放掉,需要一个时间等待计时器来使A有能力收到B超时重传的fin-ack报文。
除时间等待计时器之外,tcp还需要一个保活计时器(服务器端)来避免A突然断掉,B一直等待。