TCP原理特性详解

news2024/11/24 11:57:24


文章目录

  • 可靠传输机制
    • 1.确认应答
    • 2.超时重传
    • 2.连接管理
      • 1.三次握手
      • 2.四次挥手
  • 传输效率
    • 1.滑动窗口
    • 2.流量控制
    • 3.拥塞控制
    • 4.延时应答
    • 5.捎带应答
  • 面向字节流
    • 粘包问题
  • TCP异常情况

可靠传输机制

可靠性:即发送方知道数据是发送成功了,还是失败了。

1.确认应答

确认应答是TCP实现可靠传输最为核心的机制。


image-20230917130839885

主机A给主机B发送消息,B收到之后返回一个应答报文(ACK),A收到应答报文后就知道第一条消息发送成功了,于是继续发第二条消息…

  • 确认应答:即应答报文,也称为ACK报文。

  • 序号:类似数据(11000)等,TCP是面向字节流的,这里的11000这类数字就是1~1000个字节,每个字节都编有序号。因为字节编有序号,所以避免了发送的数据乱序的问题, 。image-20230917132307680

    TCP字节序号是依次累加的,第一条数据字节序号11000,第二条数据就是10012000。由于这1000个字节都属于一个TCP报文,所以每个TCP数据报头只存当前数据的第一个序号,比如第二条数据的TCP报文里存1001,再根据 TCP报文长度,就知道这条数据是1001~2000。

  • 确认序号:每个确认应答都带有数字(确认应答1001),这类数字就是确认序号,而确认序号只有应答报文拥有,ACK标志位为1,表示为应答报文,ACK标志位为0,表示不是应答报文。确认序号表示成功收到哪些数据,下一条数据从哪里开始发。确认序号返回的是收到当前数据最后一个字节序号的下一个序号,列如:收到11000个字节数据,返回1001,表示1001之前的数据都收到了,于是下一条消息是从编号为1001的位置开始发,即10012000。

2.超时重传

丢包分为两种情况:一是发送数据丢了,二是返回的ACK丢了。为了解决丢包问题,TCP引入了超时重传机制,在丢包的情况下,重新发送一份相同的数据。如何判断丢包呢?TCP引入了一个时间阈值,发送方传输一个数据,在一个规定的时间内,如果未收到ACK,不管三七二十一,都表示为丢包了,进行重传。

数据丢包:主机A发送的数据丢包了,在隔了一定的时间后,未收到主机B发来的确认应答,则会再次传输1~1000的数据

image-20230917142544706

ACK丢包:可以发现主机B收到了两次1~1000这个数据,TCP会根据这种重复数据进行去重,利用TCP的接收缓冲区进行去重。这个缓冲区相当于一个阻塞队列,当主机B读到了主机A发送的数据,主机B把这个数据放入这个阻塞队列中,再根据数据的序号排序、去重,如果序号重复则丢弃后来的数据。

image-20230917142620454

超时重传可能会重传几次,当重传次数达到一定的次数时,TCP会尝试重连,如果重连失败则彻底断开连接。重传的时候,第一次重传时间和第二次时间间隔不一样,重传次数越多时间间隔越大。

2.连接管理

在正常情况下,TCP要经过三次握手建立连接,通过四次挥手断开连接,所谓连接本质上是通信双方互存储了对方的信息,管理则是描述了连接如何连接和断开。

1.三次握手

举一个比较形象的列子:A先发一条消息,B收到后并响应,同时B再发送一条消息给A,A收到后并响应。

image-20230918125239110

三次握手本质上是四次交互,我们形象的把每次通信比喻成一次握手。通信双方,各自要发送一个“建立连接”的请求并各自返回对方一个ACK应答报文。由于主机B的响应和发送新消息(好啊+确认哈…)这两次交互的时间非常近,于是就把这两次交互合并为一次,也就成了三次握手;并且这两次合并是必须的,因为每次通信都需要封装分用,两次封装分用肯定要比一次封装分用的成本高。

image-20230918125939408

问题:四次合成了三次,那么直接合成两次可以完成吗?

答:显然是不能的。当主机A发送了一条消息:明天一起吃饭?主机B响应并发送新消息:好啊,确认哈?一起吃饭,别放鸽子。此时,主机A知道了主机B同意明天一起吃饭,但是主机B并不完全确定主机A会不会放鸽子。那么明天A和B可能也就吃不成饭了,也就意味着主机A和主机B连接建立不了!

三次握手的意义:一是建立通信双方的认同,保存对方的信息,二是为了验证通信双方各自的发送和接收是否正常;三是在每次交互会夹带一些重要信息,来协商一些重要的参数。

image-20230919104650158

客户端主动给服务器发起的建立连接请求,称为“SYN”/同步报文段(synchronize),对应着TCP报文结构里的“SYN”,然后服务器进行响应返回“SYN+ACK”,说明这条交互既是同步报文段,又是确认应答报文段,最后客户端返回一个“ACK”应答报文。

  • TCP连接有11种状态,分别是:LISTEN、SYN_SENT、SYN_RECEIVED、ESTABLISHED、FIN_WAIT_1、FIN_WAIT_2、CLOSE_WAIT、CLOSING、LAST_ACK、TIME_WAIT和CLOSED。

    建立连接时的状态:

  • LISTEN:表示服务器端的某个SOCKET处于监听状态,可以接受客户端的连接;

  • SYN_SENT:表示在发送连接请求后等待匹配的连接请求;

  • SYN_RECEIVED:表示在收到和发送一个连接请求后等待对连接请求的确认;

  • ESTABLISHED:表示已经建立了连接,可以进行数据传输;上图中客户端和服务器都有这个状态。

  • CLOSED表示TCP连接已经关闭 。

2.四次挥手

挥手和握手一样都是形象的比喻。四次挥手也是通信双方各自对对方发送一个断开连接的请求,再各自发送一个响应。

问题:中间两次是否能合并?(到了+你呢?)

答:显然不行,三次握手的两次交互之所以可以合并是因为这两次交互是同一时机,这一操作是纯内核操作,是我们感受不到的,当服务器收到syn后会立即返回ack;而四次挥手则不同,这两次交互是不同时机,当主机A的应用程序执行到socket的close方法时会触发FIN结束报文段,服务器接收到FIN后,内核会立即返回ACK,FIN是人为发送的,而ACK是由系统内核控制的,当主机B的应用程序执行到socket的close方法时也会触发FIN,应用程序执行到close方法前可能要经过很多道其他的程序代码,于是和ACK的时机相隔太久,也就不能合并为一次交互。

image-20230919111434977

image-20230919112122092

断开连接时的状态:

  • CLOSE_WAIT:表示被动断开连接一方等待FIN报文;

  • TIME_WAIT:表示主动断开连接的一方收到了对方的FIN报文,但是还没有发送ACK报文;

    TIME_WAIT的意义:

  • TIME_WAIT状态站在客户端视角认为已经断开连接了,但是此时TIME_WAIT会让连接状态继续保留,因为最后一个ACK还没有发出去,如果最后一个ACK丢包,服务器会进行超时重传,重新传一个FIN,客户端再重新发一个ACK,因此TIME_WAIT状态保留连接状态一定时间,就是为了有能力进行重传,如果重传的还是丢了,时间也到了,那么就认定为最后ACK没丢,直接断开连接。

  • TIME_WAIT保留时间为2MSL;(Max Segment Life,报文最大生存时

    间)2MSL表示为互联网上,两个节点之间数据传输消耗的最大时间,这个时间通常为60s。

传输效率

1.滑动窗口

活动窗口的目的是为了在可靠性传输的基础上提高传输效率。

基础的确认应答机制:主机A发一次数据,主机B只要收到一条数据就返回一个ACK,而主机A此时在没有收到ACK的时候,需要进行等待,才能发送下一条数据,每一次发送数据都要等一次,这就造成了不少的等待时间。

image-20230920101558133

加入活动窗口后的确认应答机制主机A不再需要等待第一条数据的ACK,可以一次性发送多条数据,再使用一份等待时间来等待一组数据返回的多个ACK,这就减少了多条等待ACK的时间。

下图是主机A一次性批量发送四条数据,主机B再批量返回四个ACK,收到一条数据就返回一条ACK,依次类推,只是说主机A不需要等第一个ACK,就可以连续发4条数据。

image-20230920101730003

把不需要等待就可以发送的最大的数据量就称为:“窗口大小”;上图这个“窗口大小”为4000。

发送一个窗口大小的数据后,主机A并不是要等这一个窗口大小的ACK全部返回了,才继续发送下面的数据,而是主机B接收到一条数据就返回一条ACK,主机A收到一个ACK就发一条数据,这样就保证了等待的ACK永远都是4条(窗口大小,处理的数据永远都是4条,而不是处理一条就没事做了)。

举个例子:比如一个人有4台电脑一台电脑可以刷一门课,同时只能刷4门课,需要刷满10门课,此时“窗口大小”就是4。当我刷完一门课后,手上正在刷的课为3门,那么就有一台电脑是空闲状态,于是我就可以再找一门课继续刷,一直保持刷4门课的状态。相当于用1门课的时间刷了4门课,用最少的时间刷完10门。

每次刷完一门课,就立即开始下一门,窗口大小始终未变,但是课程变了。类似于下图,本来需要等10015000的ACK,但是收到了2001的ACK,说明2001之前的数据已经被确认,此时可以立即发送50016000的数据,等待的ACK范围就成了2001~6000,这种现象看起来就像是在滑窗口,于是就形象的比喻成滑动窗口

image-20230920104420332

  • 滑动窗口情况下,丢包了怎么解决?

    1. ACK丢了:不需要做出任何处理!因为有确认序号,当返回2001的ACK,说明2001之前的数据都到达了,2001包含了1~2000的数据序号。image-20230920105210223

    2. 数据包丢了:下图显示,当10012000的数据丢了,主机B返回的是1001的ACK,意思是索要主机A1001开头的数据,主机A连续发送多条数据后收到的依旧是1001的ACK,这时主机A就会发送10012000的数据。当主机B成功收到10012000的数据后,由于主机A之前已经发送20017000的数据,并且主机B成功收到了,于是这次返回的是7001的ACK,说明7001之前的数据都收到了(包含10012000的数据),也就意味着主机A下次发送的数据是从7001开始。假设,40015000也丢包了,此时是返回的ACK是5001,而不是7001,即使主机A已经把数据发送到了7000。总结:丢哪个包就索要哪个包的数据。

      这种重传方式称为“快速重传”,表示只重传丢失的数据。

2.流量控制

滑动窗口提高了传输效率,可是窗口也不能无限大,因为接收方处理能力有限。流量控制的意义是为了根据接收方的处理能力来控制发送方的传输效率。

那么如何衡量接收方的处理能力呢?

可以根据接收方的接收缓冲区剩余大小来判断,比如传输10个,接收缓冲区还剩下20个,说明下次可以传输20个,或者30个,接收方都能处理过来。

比如主机A给主机B发送了一条数据,B就算一下接收缓冲区剩余空间,再把这个结果通过ACK返回给A,A根据这个结果来决定下次发送的窗口大小是多少,是连续发10个还是20个。

TCP报文结构里有16位窗口大小,即默认为64kb,而TCP为了让窗口大小可以更大,在选项中引入了窗口大小的扩展因子,比如扩展因子里是2,表示64kb左移2位即256kb。

image-20230920121358460

上图显示:第一次A传输了11000的数据,B返回1001ACK,接收缓冲区剩余大小为3000,A再次发送10014000的数据,B依次返回三个ACK 当B的接收缓冲区为0了,A机会进行等待,在等待时间,A会发送一个窗口探测报文来询问B的接收缓冲区是否有空余。

3.拥塞控制

流量控制和拥塞控制共同决定发送方的窗口大小。

流量控制表示接收方的处理能力;

拥塞控制表示传输过程中的中间节点的处理能力(中间节点:路由器,运营商等)。

中间节点的测量:通过实验来测试出一个合适的值。比如先发少量的数据,探探路,摸清当前的网络拥堵状态,再决定按照多大的速度传输数据;

下图表示实验中间节点的窗口大小:第0轮。窗口大小为1,没有丢包就扩大窗口,第二次就为2…以指数增长;当增长速率达到阈值时,变成线性增长;当丢包了也就是遇到网路拥堵,窗口大小一下子变为一个很小的值,再重新按指数增长线性增长,此时的增长速率阈值为上次网路拥堵的值除2…依次类推,直到找到不是网络拥堵的瓶颈并且是一个最大的值 。拥塞窗口会根据当前网络环境一直动态的调整。

image-20230920122455931

4.延时应答

延时应答:收到数据后,不是立刻返回ACK,而是稍等再返回。

在滑动窗口上进行改进,比如主机A第一次发送数据,B的原本接收缓冲区大小为1M,B计算后立即返回的ACK窗口大小为500kb,那么下次A传输的数据就是500kb;但是如果要是稍等再返回ACK,在这个稍等的时间内主机B把这个500kb给消费掉,那么返回的窗口大小就为1M,下次A就可以发1M的数据,从而提高传输效率。

image-20230920174000401

上图显示,实际上延时应答采取的方式为在滑动窗口下,ACK不再每一条数据都返回,比如上图隔一条返回一个ACK。

5.捎带应答

在延迟应答的基础上,我们发现,很多情况下,客户端服务器在应用层也是 “一发一收” 的。意味着客户端给服务器说了 “How are you”,服务器也会给客户端回一个 “Fine, thank you”;因为TCP存在延时应答,ACK等了一会,那么这个时候ACK就可以搭顺风车,和服务器回应的 “Fine,thank you” 一起回给客户端

image-20230920175409229

由于内核返回的ACK存在延时应答,于是等待,这时候应用层发了一条数据刚好和延时应答后返回的ACK时机相同,于是这两次合并为一次。

image-20230920175439006

面向字节流

粘包问题

接收缓冲区实际上是把收到的数据都放在一起,由于TCP的字节流的,但是应用层序read读取时,可以一次read一个字节或多个字节,读到哪里才算是一个完整的应用层数据报呢?这就导致可能read读取到的是半个数据报或是多个数据报。就好比下图,假设下图都是主机B返回的数据,主机A,read读取时,一次读8个字节,读取到了:“abcdefgh”,这种情况就叫粘包问题

解决方案:在应用层约定每个数据报之间用什么分隔符区分,比如用“\n",或者约定每个数据报的长度。

image-20230920180330887

TCP异常情况

  1. 进程崩溃:进程终止会释放文件描述符,仍然会完成四次挥手。和正常关闭没有什么区别。

  2. 主机正常关机:和进程崩溃一样。

  3. 主机掉电/网线断开:

    • 接收方掉电:发送方接收不到ACK,超时重传几次,会尝试重置连接,最后彻底放弃连接。
    • 发送方掉电:接收方收取不到数据,于是会周期性的发送一个消息,确认对方是否正常工作,这种操作称为“心跳包”。通过“心跳包”来确认通信双方是否正常。
  4. 进程崩溃:进程终止会释放文件描述符,仍然会完成四次挥手。和正常关闭没有什么区别。

  5. 主机正常关机:和进程崩溃一样。

  6. 主机掉电/网线断开:

    • 接收方掉电:发送方接收不到ACK,超时重传几次,会尝试重置连接,最后彻底放弃连接。
    • 发送方掉电:接收方收取不到数据,于是会周期性的发送一个消息,确认对方是否正常工作,这种操作称为“心跳包”。通过“心跳包”来确认通信双方是否正常。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1071450.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Github-使用2FA验证:使用python实现TOTP验证,python实现github的2FA验证

github新增了2FA验证了, 1、扫描二维码,获取对应字符串 或点击setup key ,获取字符串 2、使用python来生成校验码 安装: pip install pytop import pyotp key XKDRR4WH3LY2WXPH print(pyotp.TOTP(key).now()) 3、将生成的6个验证码&…

第一章 概述 | 计算机网络(谢希仁 第八版)

文章目录 第一章 概述重要内容计算机网络的一些相关知识互联网概述因特网的标准化工作互联网的组成计算机网络的类别计算机网络的性能指标计算机网络的体系结构——-分层次的体系结构 第一章 概述 重要内容 互联网边缘部分和核心部分的作用,以及分组交换的概念 计…

学习记忆——宫殿篇——记忆宫殿——记忆桩——身体——记忆星座

我们在与人攀谈的时候,可以从以下几个维度入手,如:年龄、星座、爱好、工作等。 两点记忆的技巧以及一点知识延伸 两点记忆技巧: 1、第一次见面时要创建回忆线索 2、脑中回忆交流画面,加深线索 一点知识延伸&#xff1…

NoSQL之Redis 主从复制配置详解及哨兵模式

目录 1 Redis 主从复制 1.1 主从复制的作用 1.2 主从复制流程 2 搭建Redis 主从复制 2.1 安装 Redis 2.2 修改 Redis 配置文件(Master节点操作) 2.3 修改 Redis 配置文件(Slave节点操作) 2.4 验证主从效果 3 Redis 哨兵模…

自动拟人对话机器人在客户服务方面起了什么作用?

在当今数字时代,企业不断寻求创新的方法来提升客户服务体验。随着科技的不断进步和消费者期望的提升,传统的客户服务方式逐渐无法满足现代消费者的需求。因此,许多企业正在积极探索利用新兴技术来改进客户服务,自动拟人对话机器人…

javaScript关于闭包的理解

首先在了解闭包之前,我们要了解一下环境和作用域 1.环境和作用域 日常生活中我们生活的环境由周边建设如公园,小区,超市构成的。这就构成了环境 在计算机当中环境就是一块内存的数据。 环境是有作用范围的,eg:武汉周边的建设一…

YOLOv8 Tensorrt部署详细介绍(小白从0到1,不会你砍我)

下载YOLOv8项目和Tensorrt部署项目 git clone https://github.com/xiaocao-tian/yolov8_tensorrt.git git clone https://github.com/ultralytics/ultralytics.git 下载yolov8s模型 在YOLOv8项目中新建weights文件夹,将yolov8s.pt放入 运行tensorrt项目中gen_wts…

RabbitMQ 介绍与 SpringBootAMQP使用

一、MQ概述 异步通信的优点: 耦合度低吞吐量提升故障隔离流量削峰 异步通信的缺点: 依赖于Broker的可靠性、安全性、吞吐能力架构复杂,业务么有明显的流程线,不方便追踪管理 什么是的MQ MQ(Message Queue&#xf…

选择适合建筑公司的企业网盘平台

随着城市化进程的加速,越来越多的人开始关注乡村生活品质。Z公司以其标准化产品和优质资源整合,为回乡建房人群提供了一种全新的、高品质的整体解决方案。 Z公司深入调研了10W的回乡建房人群需求,组建了设计、工艺、供应链方面的专家团队&…

KUKA机器人通过直接输入法设定负载数据和附加负载数据的具体操作

KUKA机器人通过直接输入法设定负载数据和附加负载数据的具体操作 设置背景色: 工具负载数据 工具负载的定义: 工具负载数据是指所有装在机器人法兰上的负载。它是另外装在机器人上并由机器人一起移动的质量。需要输入的值有质量、重心位置、质量转动惯量以及所属的主惯性轴。…

边坡安全监测系统:守护边坡稳定的重要工具

在工程建设中,边坡安全监测系统一直被认为是掌握边坡安全及其支护结构维护决策系统的关键支撑条件。这一系统的主要目的在于确定边坡结构的稳定性,监控支护结构的承载能力、运营状态和耐久性能,并对边坡稳定性进行实时监控。 一、边坡安全监测…

CTF学习笔记——PWN(入门)

文章目录 [toc] CTF学习笔记——PWN(入门)PWN基础概念NC题[HGAME 2023 week1]test_nc 栈溢出[HNCTF 2022 Week1]easyoverflow 伪随机数[SWPUCTF 2022 新生赛]Darling 待补充待补充 CTF学习笔记——PWN(入门) 🚀&#x…

python常用库之数据库orm框架之SQLAlchemy

文章目录 python常用库之数据库orm框架之SQLAlchemy一、什么是SQLAlchemySQLAlchemy 使用场景 二、SQLAlchemy使用SQLAlchemy根据模型查询SQLAlchemy SQL 格式化的方式db_session.query和 db_session.execute区别实测demo 总结:让我们留意一下SQLAlchemy 的 lazy lo…

电流,功率监控芯片INA226应用(基于STM32工程)

一芯片介绍 INA226是具有I2C™或SMBUS兼容接口的电流分流器和功率监控器。该设备同时监视并联电压降和总线电源电压。可编程的校准值,转换时间和平均值与内部乘法器结合使用,可以直接读取以安培为单位的电流和以瓦特为单位的功率。INA226感应共模总线电…

Spring【@Resource、@Autowired+lombook+Bean的生命周期】

Resource 和 Autowired 的区别 在Spring中找Bean的两种方式:①先根据类型查找②再根据名称查找 Autowired先根据类型查找,再根据名称查找【根据上述查找结果不唯一,再添加一个 Qualifier(value“”),就可以查找】 Resource先根据名…

Spring Cloud Gateway2之断言Predicate详解

文章目录 1. 前言2. Spring Cloud Gateway断言的种类及各自功能2.1. Path断言 PathRoutePredicateFactory2.2.Method断言 MethodRoutePredicateFactory2.3.Header断言 HeaderRoutePredicateFactory2.4.Host断言 HostRoutePredicateFactory2.5.Query断言 QueryRoutePredicateFac…

【C++】unordered_set和unordered_map介绍及使用【附OJ题】

目录 一、unordered_set和unordered_map的介绍和使用 1、介绍 2、使用及与set和map的区别 3、O(logN)和 O(1)的效率对比 二、力扣OJ题 1、重复N次的元素 2、两个数组的交集 一、unordered_set和unordered_map的介绍和使用…

AI+Social Power,开创营销新纪元 | 2023数说故事年度社媒营销盛会,10月13日邀您共同见证

尊敬的嘉宾: AIGC成为2023年最热门的关键词之一,且以惊人的速度赢得了“圈层共识”,各行业都在探索如何利用AI技术创造更多可能性。尤其在社媒营销领域,AIGC的应用已成为势不可挡的趋势:品牌们用AI造新品,…

OpenHarmony嵌套类对象属性变化:@Observed装饰器和@ObjectLink装饰器

上文所述的装饰器仅能观察到第一层的变化,但是在实际应用开发中,应用会根据开发需要,封装自己的数据模型。对于多层嵌套的情况,比如二维数组,或者数组项class,或者class的属性是class,他们的第二…

子组件跳转父组件

描述:父组件Form.vue 点击关联,弹出子组件importForm.vue 选中一条数据之后,点击确定按钮,关闭子组件importForm.vue,将子组件的内容显示在父组件Form.vue中 选中第一条数据,点击确定 父组件对应的工作内容…