TCP 协议八大核心工作机制

目录

前言

一、确认应答机制(可靠机制)

二、超时重传(可靠机制)

三、连接管理

四、滑动窗口(效率机制)

五、流量控制

六、拥塞控制

七、延时应答(效率机制)

八、捎带应答

九、粘包问题

十、异常情况


前言

        本篇博客主要介绍TCP协议中的传输层协议的一些核心的原理,包含三次握手,四次挥手;确认应答机制,超时重传等等.....

TCP协议的特点是有连接,可靠传输,面向字节流,全双工

一、确认应答机制(可靠机制)

        这个机制是实现可靠性的最核心的机制。在TCP协议中,发送方发送数据后,接收方需要对数据进行确认应答,以确保数据已经被正确接收。如果发送方没有收到确认应答,就会重新发送数据,直到接收方发送确认应答为止。这样可以保证数据的可靠传输,避免数据丢失或损坏。同时,TCP还采用了序列号和确认号的机制,用于保证数据的顺序和完整性。

        先来看一个例子:假设A同学给B同学发消息问B同学是否在家,和B同学的家里人是否在家,B同学的回答是他在家,而家里人不在家。这时候传递的就是正确的消息。但是由于网络传输可能会出现后发先至的情况,所以还可能出现错误的情况。

        可能出现的错误情况:针对两条消息,B同学先回复的是在,后回复不在,但是由于网络传输的问题,A同学就先收到了不在,接着收到在,这时候A同学就认为B同学是不在家的,而B同学的家长在家,这和B同学原本想表达的意思就不一样了。
 

 解决的办法:我们可以针对消息进行标号,这样我们就可以区分发送的先后顺序了。

        在真实的网络传输中究竟是怎样保证确认应答机制的呢?

我们可以先来看看TCP的协议段格式:

对于六位标志位:

URG:紧急指针是否有效

ACK:确认号是否有效

PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走

RST:对方要求重新建立连接;我们把携带RST标识的称为复位报文段 

SYN:请求建立连接;我们把携带SYN标识的称为同步报文段

FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文

对于32位序号和确认序号的作用: 

        发送方在发送数据时,会给每个数据段分配一个序号,接收方在接收到数据后,会发送一个确认序号,告诉发送方已经成功接收到了这个数据段。发送方在收到确认序号后,就知道这个数据段已经成功传输到了接收方,可以继续发送下一个数据段

        同时,TCP协议还会对数据进行分段和重组,确保数据的完整性。发送方会将数据分成若干个数据段,每个数据段都会有一个序号和确认序号。接收方在接收到数据段后,会根据序号将数据段重组成完整的数据,并发送确认序号告诉发送方已经成功接收到了这个数据段。

        因此,确认序号和序号在TCP协议中起着非常重要的作用,可以保证数据传输的可靠性和完整性。

        在我们真实的网络传输中,TCP并不是以“消息”为单位进行编号的,而是以字节为单位进行编号的,也就是在我们发送的消息中对消息的每一个字节进行编号,编号称为序列号,发送方发送的报文里面会包含序号,接收方会返回一个ack确认序号,发送方通过这个ack确认序号就可以知道接收方那些数据收到了,哪些数据没收到。 这也就是TCP中的确认应答机制。

        下图就是发送方和接收方的收发消息的情况示例图:

        这里再补充一下确认序号的规则:这里的确认序号不是说发送方序号是啥,确认序号就是啥,而是取发送方发过来的所有数据的最后一个字节的下一个字节的序号;

        确认序号的含义:比如这里确认序号是1001表示的是1001之前的数据我已经收到了,接下来发送方就可以发1001之后的数据了。

        以上就是确认应答机制的主要内容,确认应答主要是通过对字节进行编号的接收方是否返回ack应答报文来实现的。

二、超时重传(可靠机制)

        上面的确认应答机制其实是建立在数据传输完全正常的情况下,接收方会返回ack,但是网络传输中会出现丢包的问题。丢包就会导致ack无法正常返回。

什么是丢包和为什么会丢包:

        丢包是什么:丢包其实就是在网路传输中,中间的某个节点出现了问题,导致数据无法正常传输了,以至于数据丢失了,这就是丢包。

        为什么丢包:我们网络的传输过程中会经过一系列的交换机路由器的转发,在转发过程中,如果数据突然增多(这里的交换机路由器转发的内容是很多客户端的),导致某个交换机或路由器达到了传输的瓶颈,就会导致数据的丢失,所以就会出现丢包。

        如何解决丢包问题:在传输过程中,如果数据丢失了,那接收方就无法正确的接收到了,这时候也就不会返回ack了,在这里TCP的解决办法就是超时重传,超时重传就是将数据重新发送一遍,超时重传的次数每多一次,重传的等待时间就会增多。在多次重传都没有收到ack之后,TCP就会重置连接(重连)重连如果失败之后,就会自动断开连接了。超时重传就是尽最大的可能去传输,如果物理层方面出了问题,超时重传也就没有用了。这就是超时重传。

TCP的自动去重功能:

在上述的超时重传过程中,其实可以细分为两种情况下的超时重传:

第一种:数据在传输过程中丢包了,接收方没收到数据,自然也就不会返回ack了,这时候超时重传没有问题;

第二种:接收方已经接收到发送方的数据了,ack也已经返回了,但是ack返回过程中丢包了,这时候再重传的话,接收方就会收到两份一样的数据了。TCP对此就会在接收缓冲区根据序号自动的对数据进行去重了,所以这里我们也不需要太过于担心。这就是TCP的自动去重功能。

三、连接管理

        我们的TCP传输是有连接的,那到底TCP是如何保证连接是否能正常通信的呢,这就是接下来要介绍的TCP是如何建立和断开连接的,其实也就是通过三次握手和四次挥手来保证的。(三次握手其实就是客户端与服务器之间的三次交互,四次挥手就是四次交互)。

三次握手:本质上就是投石问路,确认通信是正常的。

        上图本质上是客户端和服务器的四次交互,但是我们这里说的三次握手其实是三次交互,上图其实中间的ack和syn可以合并为一次(如下图所示),因此就是三次握手。

        syn和ack是什么:syn和ack是TCP报文结构中六个特殊比特位中的两个比特位,默认是0,如果设为1,就表示特殊的含义,ack如果为1,说明这个报文是一个应答报文,syn如果为1,说明是一个同步报文;

        三次握手是如何确定双方接收能力和发送能力是否正常的:我们可以这样来理解,客户端问服务器说,你愿意和我建立连接吗(相当于第一个ack);服务器回答说:我愿意和你建立连接(相当于返回的ack),那你原因和我建立连接吗(相当于服务器返回的syn)。最后客户端说我也愿意(相当于最后一个ack),客户端和服务器其实就是在这样一次嘘寒问暖之后确定了双方都可以正常通信之后,建立起连接的。

        两次握手行不行:两次握手其实是不行的,两次握手就无法保证客户端和服务器双方发送和接收能力都是正常的了。假设没有最后一次客户端的ack,客户端通过发第一个syn,服务器收到并且返回syn+ack了,到这里可以说明客户端发送能力正常,服务器接收和发送能力也正常,但是因为客户端最后一次ack没返回,所以服务器会认为客户端的接收能力不行。所以三次握手是一次都不能少的。

        四次握手行不行可以,但是没必要,会浪费时间和资源。

四次挥手:

对于上图四次挥手的解释:

        FIN是什么:FIN是TCP报文结构中六个特殊比特位中的一个比特位,默认是0,如果变为1的时候代表的是该报文是一个结束报文。

        中间的ACK和FIN能不能合并为一次发送:这里的ACK和FIN一般情况下不能和为一次发送,但是有概率会合并为一次发送,因为ACK响应是由内核控制的,只要一收到消息就会立即自动返回,而FIN是由应用程序控制的,应用程序则是在socket调用close方法之后才返回的,而应用程序什么时候调用close方法这就不知道了,但是由于TCP还有延时应答机制,所以如果应用程序很快调用了close方法,就有可能合并成一次了;

        为什么三次握手的ACK和SYN可以合并为一次:ACK和SYN都是由内核来触发的,都是同一时间完成的。所以可以合并为一次发送了。

        连接到底是应该由谁发起和谁断开的: 如果是建立连接的话,发起方一定是客户端,因为连接就是因为客户端有需要才会发起连接的,因此发起方一定是客户端;而对于断开连接,由客户端和服务器双方任意一方发起都可以。(这个就类似于男女朋友,一般建立关系都是男生主动的,而分手则男生女生都有可能提出来)

四、滑动窗口(效率机制)

先来看一下一张数据传输的图片:

        上图表达的意思是每发一条数据就等待ack返回再发送下一条,这样子的话效率其实是不高的,因此TCP就引入了滑动窗口的概念。

        滑动窗口本质上就是通过一次可以发送多条消息(这个具体几条消息由什么决定在接下去的流量控制和拥塞控制中会介绍),就不需要发一次消息就停下来等待ACK的返回,可以继续发下一条消息,这样子就可以边发消息边等待ACK,效率自然就提高了,每返回一个ACK就继续发送下一条消息。这样子就好像一个窗口一直在向前移动一样,所以就形成了滑动窗口,滑动窗口效率就能在原基础上提高一些了。(如下图所示)。

滑动窗口示意图如下所示: 

滑动窗口中的一些可能出现的问题:

        滑动窗口中如果出现丢包怎么办:我们将丢包分为返回的ack丢失和数据丢失两种情况:

①ack丢失:下图中我们一次发送了6条数据,但是丢失了三条,这个丢包率非常高,但是这里却不会有任何问题,因为最后一条数据的ack报文是有成功返回的,也就是确认序号是6001的,确认序号的含义就是说明确认序号之前的数据已经是全部收到了,也就是后一个ack是可以涵盖前一个ack的。如果刚好是最后一条数据的ack丢包了,那就会超时重传。

②数据丢失:下图中是1001-2000这一条数据丢包了,因此主机B会反复的向主机A索要1001-2000的数据,主机A收到多次的索要就知道了数据大概是丢了,所以就会触发快速重传(之所以叫快速重传是因为该过程没有任何的冗余操作),只要这时候重传成功了,B就会返回确认序号是7001的ack报文,这里不会返回确认序号是2001的报文,是因为2001-7001这些数据主机B已经收到过了(都在B的接收缓冲区,只要1001-2000再补进去就完整了,如下图所示),所以就直接返回确认序号为7001的ack报文了。 

        滑动窗口是任何时候都有的吗?滑动窗口是只有大量数据的时候才会触发的一个效率机制,如果只有一条数据或者只有几条数据就不会触发滑动窗口机制。

五、流量控制

       我们上面通过滑动窗口的机制来提高了传输的效率,我们如果不考虑接收方处理数据的速度,可以得出结论:滑动窗口越大,传输的效率也就越高;但实际接收方的处理速度是有限的,所以滑动窗口太大的话,数据发送太快,接收方处理不来就可能会出现丢包,丢包又要重传,效率又会降低,因此这里我们倒不如让滑动窗口的大小适中,发送方不发太快,就不会出现太大的问题。

        发送方如何知道滑动窗口大小:在TCP报文中,有一个16位的窗口大小的字段,发送方就可以通过接收方返回的ack报文中的窗口大小的字段来确定滑动窗口大小。

        接收方是如何控制滑动窗口大小的:接收方有一个接收缓冲区,在接收缓冲区中,当有数据发送过来时,接收方就会返回ack应答报文,接收方就会在这个应答报文中添加上这时候缓冲区剩余的空间的大小,剩余的空间大小就会是滑动窗口大小,这里衡量的只是接收方的处理能力。(实际上是和拥塞控制共同决定的,这里暂不考虑拥塞控制)

        接收方的接收缓冲区如果满了发送方怎么办:接收缓冲区如果满了之后,接收方会将ack报文中的窗口大小设置为0,这时候发送方就会知道接收缓冲区满了,发送方就会定时发送一个窗口探测数据报,当接收方返回的窗口大小不再是0的时候就继续发送数据了。

下图就是流量控制的大致工作过程:

六、拥塞控制

        拥塞控制其实就是用来衡量中间节点交换机路由器的传输能力的机制;

        为什么需要衡量中间节点的转发能力:网络传输的过程中,中间会通过许多的交换机和路由器的转发,而这里的转发数据的能力,则取决于转发能力最小的交换机/路由器,也就是我们熟悉的木桶效应,这时候我们上面的滑动窗口大小只是由接收方的接收缓冲区来决定的,所以假如这时候转发的路上有个交换机转发的能力非常弱,而我们又发的非常快,就会导致数据的大量丢包,这时候我们就需要考虑交换机路由器的转发能力了。但是中间节点上交换机路由器这么多,我们该怎么来确定这时候的窗口大小呢?

        如何衡量中间节点的传输能力:这个传输能力的确定不同于上述流量控制那样,直接通过接收缓冲区之类的或公式直接计算出来,TCP中是利用实验的方式来确定的,大概的过程是这样的:刚开始先以一个小的速率发送数据,如果没出现丢包情况,则继续增大速率,一旦出现丢包情况,立即把速率调小,重复上述过程,就可以动态得到一个滑动窗口的值,之后再从流量控制得到的值和拥塞控制得到的值进行比较,去较小值作为滑动窗口的大小。

        拥塞控制实验过程如下图所示:从一个较小的值开始发送,接着以指数的速度增长,增长到一定的阈值后,再以满增长的速率增长,直到出现丢包之后,又迅速降低到较小值,接着再以指数速度增长到新阈值,,再以慢速度增长,直到丢包,再迅速降到较小值;拥塞控制就是这样的一个循环的过程。

七、延时应答(效率机制)

        延时应答是什么和如何提高效率:延时应答就是接收方收到数据之后,并没有立即返回ACK数据报,而是稍等一会再返回,再等待返回的过程中,接收方就可以趁着延时的时间来多处理接收缓冲区的数据,多处理一些数据之后,接收缓冲区空间就变大了,返回给发送方的窗口的值就变大了,这样效率就提高了。

        是否所有的报都会延时应答:延时应答一般是有两个原则:数量限制和时间限制。数量限制是当收到N条消息了就返回,时间限制是延时时间达到了N 毫秒就返回,只要满足其中之一,就会返回了。

八、捎带应答

        捎带应答是什么:是基于延时应答的一种机制,具体是指在发送方向接收方发送数据的时候,接收方可以将应答消息合并到自己的数据包中,从而减少应答消息的数量,提高网络的传输效率。

        捎带应答机制的优点和缺点:优点在于可以减少ACK应答消息的数量,从而减少网络传输的开销和延迟,提高网络传输的效率。但是,捎带应答机制也存在一些缺点,如可能会导致数据包的延迟和网络拥塞等问题,需要在实际应用中根据具体情况进行权衡和选择。

九、粘包问题

        什么是粘包问题:我们知道UDP是以数据报为单位,一个数据报就是一条消息;而TCP是面向字节流的,发送的数据就是以字节为单位的,这就不像数据报那么容易区分一条消息,这时候可能就会出现发送的消息无法被正确识别,上一条消息可能会和下一条消息的一部分连在一起了,这就是粘包问题。

        如何解决粘包问题:粘包问题的本质就是因为发送消息以字节为单位而无法正确区分一条消息导致的,因此我们给每一条消息都来一个”约定“就可以了,比如约定以特殊符号结尾;或者以开头的4个字节来记录消息的长度,先读前四个字节的存储的长度n,得到长度n后往后再读n个字节,这样子就可以解决粘包问题了。

十、异常情况

我们这里说到二点异常情况主要是当进程或者设备在非正常情况下被关闭了,会出现什么情况;

        第一种情况:进程关闭或进程崩溃:这时候进程已经没了,socket是文件,也随之被关闭了,虽然进程和socket都没了,但是连接还在,仍可以正常四次挥手,断开连接。

        第二种情况:主机关机(正常流程关机,):在这种情况下,所有进程都会被先关闭,这时候也会触发四次挥手,如果挥完是最好,如果没挥完,比如对方发的FIN过来了,但是我们由于关机了这边没有响应ACK。对方就会继续重传FIN,重传几次之后,如果都没有ACK返回,会尝试重置连接,如果还不行,就会直接释放连接了。

        第三种情况:主机断电(就是突然拔掉电源的情况,不考虑笔记本):这时候可以分两种情况讨论:

(1)我方是接收方,对方是发送方:对方(发送方)会收不到接收方返回的ACK,接着触发超时重传,再不行就重置连接,最后会释放连接。

(2)我方是发送方,对方是接收方:如果是接收方就无法知道是来不及发新数据还是直接没了;

        TCP在这里的解决方案是这样的:TCP内置了心跳包,这是一个保活机制,对方是接收方,接收方会定期给发送方发送一个心跳包,发送方就会返回一个信号作为响应,如果发的每一个心跳包都有及时的响应,说明发送方的状态正常,如果没有响应,就像是心跳没了,就可能是挂了。多次之后就可以判断发送方挂了。

        心跳包的概念:心跳包属于是一个保活机制,接收方会定时给发送方发送一个心跳包信号,发送方会返回响应,如果接收方多次没有收到响应之后就可以确定发送方挂了。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值