• 网络原理---拿捏TCP机制原理


    以下介绍TCP通信的十大特性!!

    确认应答机制

    在这里插入图片描述
    就像我们平时在聊微信的时候,用户A向用户B发一个“hello”,用户B回复一个“hi”。
    收到回复“hi”之后,我们就可以确定用户B收到我的消息了。但是当用户B不回复的时候,我们就不知道消息是否发送成功。(网络环境非常复杂,不一定每次传输数据都能成功)。

    确认应答机制就是这样的,它在发送数据后,还会返回一个消息告诉你发送成功了,这个返回的消息被称为“应答报文”。

    问题一:但是同时用户B可能也要发送一个数据给用户A,那么这个时候怎么区分返回的消息是“应答报文”还是“真实的数据”呢?
    TCP就使用6个特殊标志位中的“ack”来区分,如果ack这一位为0,则是普通报文(也就是真实的数据);如果ack这一位为,则是应答报文。

    问题二:如果同时传输多条消息,怎么能保证消息是一一对应的,不发生歧义呢?
    在这里插入图片描述
    通过分别编号来保证没有歧义。这时候就用到32位序号和32位确认序号:
    32位序号:用在发送数据的一方
    32位确认序号:用在做出应答的一方,并且只对“应答报文”有效

    在这里插入图片描述
    由于TCP是字节流,所以编号的时候以字节为基本单位。举例说明双方交互的过程:

    发送端:发送序号为1 ----报文长度为1000字节
    响应端:发送确认序号为1001 ---- 是由序号和报文长度计算出来的 含义:我已经收 到了1-1000字节的数据,你可以继续发送1001字节之后的数据
    发送端:发送序号为1001 ----报文长度为1000字节
    响应端:发送确认序号为2001---- 是由序号和报文长度计算出来的 含义:我已经收 到了1001-2000字节的数据,你可以继续发送2001字节之后的数据

    问题三:序号和确认序号都是32位的,不会溢出吗?

    32位保存的数据是:0-42亿9千万 ,也就是4G 大概率不会溢出
    就算溢出了,前面的序号已经用过了,从头开始重新编号即可

    通过这样,确认应答机制就保证了TCP传输的可靠性。同时,确认应答机制是保证TCP可靠传输最核心的机制。

    超时重传机制

    在这里插入图片描述

    如果在网络传输的过程中,发生了丢包:把用户A发送的数据丢了,即把“hello”丢了;或者 把用户B响应的数据丢了,即把“hi”丢了。这是一个非常严重的问题。TCP中就引入了超时重传机制来解决这个问题。

    • 发送端丢包

      如果用户A在过了一段时间后,还没有收到响应,他就认为数据丢了。会重新发送一次数据

    • 响应端丢包

      如果用户A在过了一段时间后,还没有收到响应,他同样认为数据丢了。也会重新发送一次数据。但是数据发送成功了只是响应丢了而已,因此响应端就会收到两条,甚至多条相同的数据。这时,响应端这边就会针对相同的数据进行去重(根据序号去重),使响应端这边只处理一条数据。

    超时的时间该如何确定呢?

    超时等待的时间并不是均等的,而是逐渐变大的。比如,丢包的概率是1% 那么第二次丢包的概率就是1% * 1% = 0.01% 概率较小,换句话说就是大概率会到达的不需要重传了。等待的时间就会更长一点。
    如果重试了几次之后,任然无法传输数据,就会让TCP断开重连
    如果还是连不上,就彻底断开连接不再尝试。

    连接管理机制

    连接管理机制:描述的是TCP建立连接和断开连接的过程。

    TCP的连接,只是一个逻辑上的“虚拟的连接“,并不是像网线一样真正的连接起来。

    主机A和主机B建立连接:
    主机A的系统内核里:记录一个数据结构,包含了和他连接的对方是谁(IP、端口号、协议)
    主机B的系统内核里:记录一个数据结构,包含了和他连接的对方是谁(IP、端口号、协议)

    三次握手(建立连接)

    三次握手的流程

    在这里插入图片描述
    在这里插入图片描述

    问题: 怎么知道发送方发送的是”申请连接“还是“真实的数据”呢?

    使用6位特殊标志位中的syn来表示,如果syn这一位为0,表示是普通报文(真实的数据);如果syn这一位为1,表示是同步报文(申请建立连接);

    在这里插入图片描述

    为什么要建立连接? 建立连接的意义是什么?

    1. 投石问路 检查一下当前的网络是否畅通
    2. 检查通信双方的发送能力和接收能力都是正常的
    3. 三次握手也在协商一些重要的参数

    三次握手的状态转换

    在这里插入图片描述

    LISTEN:服务器启动之后,绑定端口之后(new ServerSocket完成后),表示服务器状态良好,可以让别人建立连接

    ESTABUSHED:表示连接已经建立,连接很稳定

    四次挥手(断开连接)

    四次挥手的流程

    在这里插入图片描述

    同样的,断开连接时发送的消息也需要和真实的数据区分开。

    使用6位特殊标志位中的fin来表示,如果syn这一位为0,表示是普通报文(真实的数据);如果syn这一位为1,表示是申请断开连接;

    在这里插入图片描述

    四次挥手的状态转换

    在这里插入图片描述

    CLOSE_WAIT:表示等待socket调用close方法断开连接

    TIME_WAIT:表示主动发起断开的一方进入等待 等待收到fin

    注: 在处理完最后一个ack之后,不能立即断开连接,而需要继续保持一段时间。这是为了万一最后一个ack丢了还有机会进行重传。

    如果最后一个ack丢包了,此时就会重发一个fin; 如果最后一个ack没有丢包,一段时间后,没有fin重传过来,就认为ack顺利到达了。

    滑动窗口机制

    滑动窗口机制是提高tcp传输效率的有效机制。
    在这里插入图片描述
    在这里插入图片描述

    上述我们讨论的都是正常情况,如果发送丢包了会怎样呢?

    • ack丢包

    在这里插入图片描述

    • 数据报丢包

    在这里插入图片描述

    上述过程中,重传的效率是非常高的,也称为“快速重传”。
    快速重传:是搭配滑动窗口机制的超时重传,如果传输的数据很多,是批量传输,就使用快速重传
    超时重传:TCP默认的丢包后的解决方案。在传输的数据很少时使用,而且在批量传输中,最后一条数据丢包了也被使用。

    窗口的大小可以无限大吗? 越大效率越高?

    窗口越大传输的效率确实是越高的,但是窗口不能无限的大。

    因为:窗口太大时,接收方的处理速度跟不上发送方的发送速度,就会导致接收方丢掉一些数据。这些丢掉的数据还得重传,接收方的处理速度仍然跟不上。这样就起不到提高效率的作用。

    流量控制机制

    接收方的处理速度是有限的,我们就需要在滑动窗口机制上对发送速率做出限制,让窗口不要太大也不要太小。这就引入了流量控制机制。

    接收方的接收速率如何量化呢?
    在这里插入图片描述

    怎样让发送方知道剩余空间有多大呢?

    在ack应答报文中把剩余空间的大小返回。发送方根据情况在16位窗口大小中选择合适的窗口大小进行下次的传输。

    16位窗口大小规定窗口最大是64k吗?

    不是的。可以通过窗口的扩展因子使其更大。

    在这里插入图片描述

    拥塞控制机制

    我们知道接收方的接收效率之后,发送方就可以只按照这个效率来发送数据吗?

    不是的。在接收方和发送方之间还有很多的节点进行转发,我们也应该考虑一下这些节点的转发效率。

    在这里插入图片描述

    我们怎样能知道中间节点的转发效率呢?

    进行实验:一开始时,先发少量的数据,窗口较小。如果不丢包,就要放大窗口,先让窗口指数增长,达到阙值后再让窗口线性增长。发生丢包了,就让窗口大小回到最初值,再重复刚才的过程,同时降低阙值为刚才丢包时阙值的一半。如此反复…

    在这里插入图片描述

    延迟应答机制

    延迟应答机制也是用来提高效率的
    在这里插入图片描述
    在这里插入图片描述

    捎带应答机制

    捎带应答机制是在延迟应答机制的基础上引入的。

    在网络通信中,典型的通信模型是”一发一收“。TCP中只要把数据传输过去,对方收到数据了就会通过内核返回一个ack报文,另外的业务数据会通过应用程序负责传输,再收到一个ack报文。

    中间进行的两步:内核返回ack报文和应用程序返回业务数据,本来是不同时机传输的,不能合并在一起。但是引入了延迟应答机制后,如果这两步操作间隔的时间不长,就会合并成一个响应、一次传输过去。这就是捎带应答机制。

    在这里插入图片描述

    粘包问题

    在面向字节流传输时,都会遇到一个”粘包问题“。
    在这里插入图片描述
    主机A给主机B传输数据后,主机B都把它们保存在主机的接收缓冲区中,需要使用的时候再拿出来。但是,由于是面向字节流传输的,就不知道从哪儿开始到哪儿结束才是一个完整的数据。

    解决:

    1. 通过分隔符。比如:约定使用”;“作为包结束的标志
    2. 通过指定包的长度。比如:在数据包的开头处指明长度。

    注:UDP没有这个问题。因为它是面向数据报的

    TCP中的异常处理

    TCP在连接时如果遇到了异常该怎么办?

    1. 程序奔溃了,进程异常退出。

      操作系统就会回收进程的资源。相当于调用了socket的close方法,会触发fin报文,和普通的”四次挥手“一样。

    2. 正常关机。

      关机的时候会强制退出所有进程并回收资源,和上面一样会触发fin报文,和普通的”四次挥手“一样。

    3. 主机掉电

      • 掉电的是接收方

        此时发送方不知道对面掉电了,会继续发数据。但是收不到ack报文,会进行超时重传,重传几次之后仍然没有ack报文,会断开连接并重新连接再重传(重置连接会用到6个特殊标志位的rst 如果rst这一位为1 则是复位报文段,进行重新连接),如果还没有ack报文,就会放弃连接。

      • 掉电的是发送方

        接收方等一会儿后就会发送一个”心跳包“(周期性触发,不懈怠任何业务数据),如果对方不返回”心跳包“,说明心跳遗失了,就放弃连接。

    4. 网线断开

      双方主机都以为对方掉电了,分别执行上述主机掉电的两种情况。

    总结

    在这里插入图片描述

  • 相关阅读:
    如何预防最新的Mallox变种malloxx勒索病毒感染您的计算机?
    5. Spring源码篇之BeanDefinition
    Python程序化生成三维场景【PyPRT】
    JVM理解(二)
    做短视频必须要知道的几个视频设置参数,爆款必备。
    分享几个Linux几个有趣且实用的命令
    Linux Shell脚本一文读懂
    java计算机毕业设计小说阅读网站源程序+mysql+系统+lw文档+远程调试
    代码随想录 Day - 59|#647 回文字串|#516 最长回文子序列
    【23-24 秋学期】NNDL 作业5 第四章课后题
  • 原文地址:https://blog.csdn.net/weixin_62976968/article/details/134220909