当前位置: 首页 > news >正文

【网络】详解TCP协议中的可靠传输

【网络】详解TCP协议中的可靠传输

  • 一. TCP协议段格式
  • 二. 确认应答——确保可靠性的核心机制
    • 1.确保时序
    • 2.确保发送方知道数据是否被对方接收到
  • 三. 超时重传
    • 1. 发送的数据丢包
    • 2. ACK报文丢失

一. TCP协议段格式

在这里插入图片描述

TCP协议段格式相比UDP要复杂很多,很多内容需要我们了解TCP的一些特性后才能理解,为了理解TCP传输的可靠性,此处需要重点关注32位序号,32位确认序号,ACK这几个组成部分。

二. 确认应答——确保可靠性的核心机制

这里所谓的可靠性,并不是说我们发出的数据对方一定会接收到(真实的网络情况特别复杂,各种意外情况都存在,比如:挖掘机铲断网线/光纤、接收方停电),而是说尽可能地去保证对方能够接收到数据,并且发送方能够知道对方是否有收到这部分数据。

1.确保时序

由于真实的网络情况比较复杂,极有可能出现后发先至的情况,那此时表达的逻辑含义就有可能出现错误。
在这里插入图片描述
为了解决这个问题,引入了32位序号,32位确认序号,对数据进行编号,应答报文里就告诉发送方说,我这次应答的是哪个数据。
在这里插入图片描述
由于TCP是面向字节流的,所以编号也是相对于字节。TCP就对每个字节都进行了编号(实际情况不是从1开始编号,这里是简化了模型)。
在这里插入图片描述
那这里的32位序号存储的就是发送数据的第一个字节的编号;32位确认序号存储的就是本次发送数据的最后一个字节的序号+1。(比如这张图片中的序号1和确认序号1001)。
对数据进行编号后,想要达到不出现“后发先至”的情况,实际上还依赖于接收缓冲区。即数据到达接收方后并不会被应用层直接读走,而是要在接收缓冲区排好顺序,再依次读走,如果出现“后发先至”的情况,数据就会在接收缓冲区等待序号靠前的数据。

2.确保发送方知道数据是否被对方接收到

这个有赖于“ACK”(acknowledge)的作用,上面图片中提到的确认应答(应答报文,无载荷,只是告诉对方数据收到或没有收到)。在正常发送的报文中,ACK这一位为0,而在应答报文中,这一位为1。

结合ACK和序号/确认序号
在这里插入图片描述
如果没有返回确认应答(ACK报文)或者返回的确认应答中确认序号不对(比如发送数据1001~2000之后,仍然返回确认序号为1001的ACK报文),此处就要涉及到超时重传

三. 超时重传

没有收到ACK报文的情况主要有两种:
在这里插入图片描述

1. 发送的数据丢包

这种情况接收方本来就没有接收到数据,此时重传没有任何问题。

2. ACK报文丢失

这种情况下也会引起超时重传,但显然此时接收方已经拿到了数据,只是没有返回ACK报文而已。此时重传数据,就会引起数据的重复。那这样的问题如何解决呢:
答案是依赖于接收缓冲区的去重功能核心判定依据为数据的序号。此处可能有以下几种情况:

  1. 数据还在接收缓冲区里,没被应用程序读走
    这种情况比较简单,此时就是拿着新收到的数据的序号,和缓冲区中的所有数据的序号对一下,有一样的就是重复发送,就要把新收到的数据丢弃掉。
  2. 数据已经被应用程序读走
    应用程序从接收缓冲区中读取数据是按照序号的先后顺序,连续读取的。一定是先读序号小的,再读序号大的数据。此时socket api就可以记录上次读的最后一个字节的序号是多少。那如果重传来的数据序号比这个记录值小,就说明重复了,会被抛弃掉。

虽然数据包会被丢弃掉,但是仍然要返回ACK报文,否则发送方没有接收到ACK报文,就会继续重传。

但是重传也不是无限的去重传,重传过程也有一定的策略:

  1. 重传次数是有上限的,重传到一定次数,如果还没有ack,就尝试“复位”连接,如果仍然不行,就单方面的放弃连接。
  2. 重传会随着重传次数的增加越来越慢,重传频率会越来越低。

比如说在一次网络通信的过程中,丢包的概率为10%(相较于现实情况很大,为了简化模型),那传输一次的成功率就是90%,传输两次的成功率就是99%(90%+10%*90%),传输三次的成功率就是99.9%(99%+1%*90%)…

也就是说如果多次传输仍不能到达,大概率是出现了比较严重的网络问题,此时少重传几次,也可以节约开销。

http://www.lryc.cn/news/457390.html

相关文章:

  • 【Python实例】Python读取并绘制nc数据
  • swift使用llama3.2-vision微调xray数据集
  • 学习小课堂
  • stm32学习笔记-RTC实时时钟
  • 简历中的期望薪资怎么定?
  • MySQL 中的 GROUP BY 使用
  • 在 ubantu 20.04 云服务器上基于 bochs 编译 linux0.11
  • docker-compose安装部署和使用
  • Java之静态
  • PCB缺陷检测数据集 xml 可转yolo格式 ,共10688张图片
  • 【linux开发-驱动】-设备树
  • 不动产证ocr识别场景解析、房产证识别API
  • gpg 密钥生成、导入、导出、自动输入密码
  • 新个性化时尚解决方案!Prompt2Fashion:自动生成多风格、类型时尚图像数据集。
  • 软件设计师——计算机网络
  • Python 实现电话号码和Email地址提取程序
  • JavaGuide(3)
  • 微信小程序15天
  • 用Python制作数据可视化仪表盘:使用Dash与Plotly构建实时交互式仪表盘
  • 干部管理系统:全面提升干部管理效能
  • Java之方法
  • MyBatis 数据表与实体映射的隐藏陷阱
  • leetcode-239. 滑动窗口最大值
  • springboot项目中开启mybatis的sql日志
  • 卷积的计算——nn.Conv2d(Torch.nn里的Convolution Layers模块里的Conv2d类)
  • 确保接口安全:六大方案有效解决幂等性问题
  • 代码随想录算法训练营第二十九天| 93. 复原 IP 地址,78. 子集, 90. 子集 II
  • 【WebGis开发 - Cesium】三维可视化项目教程---初始化场景
  • 点云中ICP算法的详解
  • 抽象类Abstart Class