【Linux网络】详解TCP协议(3)

图片名称
🎉博主首页: 有趣的中国人

🎉专栏首页: Linux网络

🎉其它专栏: C++初阶 | C++进阶 | 初阶数据结构

在这里插入图片描述

小伙伴们大家好,本片文章将会讲解 TCP的流量控制和滑动窗口 的相关内容。


如果看到最后您觉得这篇文章写得不错,有所收获,麻烦点赞👍、收藏🌟、留下评论📝。您的支持是我最大的动力,让我们一起努力,共同成长!

文章目录

  • `1. 流量控制`
    • ==<font color = blue><b>🎧1.1 流量控制是什么🎧==
    • ==<font color = blue><b>🎧1.2 如何控制发送方的速度🎧==
  • `2. 滑动窗口`
    • ==<font color = blue><b>🎧2.1 什么是滑动窗口🎧==
    • ==<font color = blue><b>🎧2.2 深入理解滑动窗口🎧==



上一篇文章中,博主介绍了 :

  • TCP 的三次握手和四次挥手;

建议将上一篇文章看完之后再来看这篇文章,链接如下:

【Linux网络】详解TCP协议(2)

那么接下来正片开始:



1. 流量控制


🎧1.1 流量控制是什么🎧


  • 接收端处理数据的速度是有限的, 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送, 就会造成丢包;
  • 继而引起丢包重传等等一系列连锁反应;
  • 因此 TCP 支持根据接收端的处理能力, 来决定发送端的发送速度。 这个机制就叫做流量控制(Flow Control)。
  • 总的来说就是根据接收方的接受能力控制发送方发送数据的速度。

🎧1.2 如何控制发送方的速度🎧


  • 如何控制发送方的发送数据的速度分为两种情况:
    • 一种是接收方接收缓冲区太大;
    • 另一种是接收方接收缓冲区太小。

16位窗口大小

  • 首先回顾一下TCP报头:

在这里插入图片描述

  • 在报头中存在 16位窗口大小,这个窗口大小就是接收方用来通知发送方它的接收缓冲区大小而存在的。
  • 当接收方接收缓冲区大,回复的ACK中的窗口大小就大,反之亦然;

那么这个时候很多人可能会有一个疑问,那么在发送方第一次给接收方发送消息的时候是怎么知道窗口大小的呢?

  • 其实虽然是第一次发送消息,但是他们双方在三次握手建立连接的时候,接收方就已经给发送方发送了携带ACK的数据包;
  • 这个时候就已经给发送方通告了接收方接收缓冲区的大小。
  • TCP报文中窗口大小是16位的,那么最大的窗口大小就是 2 16 − 1 = 65535 ( K B ) 2^{16} - 1 = 65535 (KB) 2161=65535(KB),但是真的是这样的吗;
  • TCP报头中,除了 20Byte 的固定的TCP报头大小,还有个40Byte的选项,在这里面包含了窗口扩大因子M实际上的窗口大小就是窗口字段的值左移M位。

PSH 标志位

  • 当接收方接收缓冲区的大小很小,甚至为 0 0 0 的时候,怎么办呢?一般有三种做法:
  • 首先当窗口大小为 0 0 0 的时候,如果过了一段时间接收方的接收缓冲区扩大了,就会给发送方发送一个窗口更新通知,告诉发送方可以发送数据了;
  • 当然,如果过了超时重传的事件之后,方式方还没有接收到窗口大小变化的通知,发送方也会不断地向接收方发送窗口探测的数据包,如果发现接收方回复的ACK的数据包中窗口大小变大了,就会发送数据了;
  • 但是如果接收方的接收缓冲区长时间没有变化,发送方也会发送一个带有PSH标志位的报文,通知接收方得快速地处理接收缓冲区中的数据。

URG标志位

这样看来,我们已经学习了五个标志位,就差最后一个URG标志位了,那我们就来讲解一下URG标志位吧!

  • 如果在TCP报头中URG标志位置 1,说明报头中的16位紧急指针是有效的;
  • 这个紧急指针代表着在TCP的数据中,和首位置的偏移量是多少
  • 一般在TCP中紧急数据只能有 1 B y t e 1 Byte 1Byte

send()recv() 系统调用中都有紧急数据的设置,我们再来看一下接口:

  • ssize_t send(int sockfd, const void *buf, size_t len, int flags);
    • 使用 send() 系统调用发送数据时,可以选择将带外数据发送到指定的套接字。通过设置标志参数中的 MSG_OOB可以标识要发送的带外数据
    • 其中,flags 参数可以传递 MSG_OOB,以指示发送的字节是带外数据。
  • ssize_t recv(int sockfd, void *buf, size_t len, int flags);
    • 使用 recv() 系统调用接收数据时,也可以指定标志以接收带外数据。通过设置标志参数中的 MSG_OOB接收方可以读取带外数据
    • 其中,flags 参数可以传递 MSG_OOB以指示接收带外数据


2. 滑动窗口



在讲解完流量控制和超时重传机制,其实还是有两个问题:

  • 发送方如何根据接收方的窗口大小发送数据呢?
  • 超时时间内,数据并没有被丢弃,那存储在哪里了呢?


为了理解这两个问题,我们得先学习滑动窗口。


🎧2.1 什么是滑动窗口🎧


  • 博主在 TCP第一篇文章 中讲过,发送方可以一次性给接收方发送多条数据,例如下图:

在这里插入图片描述

  • 这样发送数据就可以大大提高效率,因为可以在一个时间段发送多条数据。
  • 而发送方就规定一个概念:滑动窗口,并且在滑动窗口内的数据可以直接发送,暂时不用收到应答。
    • 在窗口左侧的数据就是已发送,已确认了的;
    • 在窗口右侧的数据就是未发送,未确认;
    • 在窗口中的数据就是等待发送的数据。
  • 而滑动窗口的大小就是对方同步给我的接收缓冲区的大小,即对方的接受能力(暂时)。

滑动窗口抽象图

在这里插入图片描述


🎧2.2 深入理解滑动窗口🎧



那么依然有几个问题:

滑动窗口可以变大吗?
滑动窗口可以变小吗?
滑动窗口可以向左移动吗?

OK,那么接下来就来解答这几个问题。


  • 滑动窗口本质上就是对方接受能力的大小,即对方接收缓冲区的大小;
  • 所以如果对方接受能力变大,那么滑动窗口就会变大,反之亦然
  • 如果对方的接收缓冲区中已经没有空间了,即对方接收缓冲区满了,那么滑动窗口的大小自然就变成了 0 0 0
  • 滑动窗口是不能向左滑动的。因为在窗口左边的数据是已发送已确认了的,所以就不可能再重新发送一次了

滑动窗口表示方法

  • 博主之前讲解过,缓冲区可以想象成一个很大的数组,那么缓冲区中的每一个数据就天然有了一个下标;
  • 那么滑动窗口中的数据就也有自己的下标;
  • 当接收方给我回复ACK的时候,在TCP报头中有确认序号,所以这个序号就可以代表窗口的起始地址,而报头中窗口的大小就是滑动窗口的大小
  • 这样我们就可以用几行代码表示窗口的起始地址以及结束地址:
    • win_start = ack_seq;
    • win_end = win_start + win_size;
    • 这样我们就可以直观的理解什么是窗口的变大、变小甚至为 0 0 0,以及为什么不能向左移动;
  • 当然缓冲区的大小不可能是无穷大的,所以在底层应该使用环形队列来实现的,可能会用取模运算来实现

滑动窗口丢包问题

如果滑动窗口中有数据丢包应该怎么办呢?丢包起始可以分成三种情况:

  • 头部丢包;
  • 中间丢包;
  • 为不丢包;
  • ACK丢包

先来看一下头部丢包:

在这里插入图片描述

  • 确认序号的定义是表示接收端这个序号之前的所有数据我已经收到了;
  • 那么假设头部丢包,接收方发给发送方的TCP报文中,确认序号就一直是 0 0 0(上图的情况)。
  • 那么发送方接收到所有报文中确认序号就都是 0 0 0(上图的情况);
  • 当发送方接收到连续三条相同的确认应答,就会进行重传;
    • 这种机制叫做快速重发机制,又称为快重传。
    • 快重传机制和超时重传机制并不冲突,超时重传机制相当于是给快重传机制兜了底。
  • 上图如果发生了快重传,并且接收方接收到了数据,那么下一次的确认序号就是 8001 8001 8001

中间数据和尾部数据丢包:

  • 当中间数据或者尾部数据丢包,那么发送方收到的确认序号就是丢包的那个部分的开始序号
  • 由于滑动窗口的起始地址就是等于确认序号,因此丢包的那部分数据就变成了头部,进而全部转换成了头部数据丢包。

ACK丢包:

在这里插入图片描述

  • 这种情况并不要紧,因为可以通过后续的ACK确认接收方是否收到了。

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

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

相关文章

MySQL - 单表查询

DQL (数据查询语言)是用来查询数据库表中的记录的操作。在实际的业务系统中&#xff0c;查询操作的频率远远高于增删改。常见的查询操作包括条件查询、排序、分组等。 1. DQL 语法 SELECT 字段列表 FROM 表名列表 [WHERE 条件列表] [GROUP BY 分组字段] [HAVING 分组后条件]…

57 长短期记忆网络(LSTM)_by《李沐:动手学深度学习v2》pytorch版

系列文章目录 文章目录 系列文章目录长短期记忆网络&#xff08;LSTM&#xff09;门控记忆元输入门、忘记门和输出门候选记忆元 (相当于RNN中计算 H t H_t Ht​)记忆元隐状态 从零开始实现初始化模型参数定义模型训练和预测 简洁实现小结练习 长短期记忆网络&#xff08;LSTM&a…

QT基础 制作简单登录界面

作业&#xff1a; 1、创建一个新项目&#xff0c;将默认提供的程序都注释上意义 01zy.pro代码 QT core gui # QT表示要引入的类库 core&#xff1a;核心库例如IO操作在该库中 gui&#xff1a;图形化界面库 # 如果要使用其他类库中的相关函数&#xff0c;则需要加对…

【深度学习】—线性回归 线性回归的基本元素 线性模型 损失函数 解析解 随机梯度下降

【深度学习】— 线性回归线性回归的基本元素 线性模型损失函数解析解随机梯度下降小批量随机梯度下降梯度下降算法的详细步骤解释公式 线性回归 回归&#xff08;regression&#xff09;是能为⼀个或多个⾃变量与因变量之间关系建模的⼀类⽅法。在⾃然科学和社会科学领域&…

正点原子——DS100示波器操作手册

目录 基础按键&#xff1a; 快捷键 主界面&#xff1a; 垂直设置&#xff1a; 通道设置&#xff1a; 探头比列&#xff1a; 垂直档位&#xff1a; 垂直偏移&#xff1a; 幅度单位&#xff1a; 水平设置&#xff1a; 触发方式&#xff1a; 测量和运算: 光标测量&am…

如何用好通义灵码企业知识库问答能力?

通义灵码企业版&#xff1a;通义灵码企业标准版快速入门_智能编码助手_AI编程_智能编码助手通义灵码(Lingma)-阿里云帮助中心 通义灵码提供了基于企业知识库的问答检索增强的能力&#xff0c;在开发者使用通义灵码 IDE 插件时&#xff0c;可以结合企业知识库内上传的文档、文件…

《深度学习》【项目】OpenCV 发票识别 透视变换、轮廓检测解析及案例解析

目录 一、透视变换 1、什么是透视变换 2、操作步骤 1&#xff09;选择透视变换的源图像和目标图像 2&#xff09;确定透视变换所需的关键点 3&#xff09;计算透视变换的变换矩阵 4&#xff09;对源图像进行透视变换 5&#xff09;对变换后的图像进行插值处理 二、轮廓检测…

YOLOv8改进,YOLOv8主干网络替换为GhostNetV3(2024年华为提出的轻量化架构,全网首发),助力涨点

摘要 GhostNetV3 是由华为诺亚方舟实验室的团队发布的,于2024年4月发布。 摘要:紧凑型神经网络专为边缘设备上的应用设计,具备更快的推理速度,但性能相对适中。然而,紧凑型模型的训练策略目前借鉴自传统模型,这忽略了它们在模型容量上的差异,可能阻碍紧凑型模型的性能…

【d53】【Java】【力扣】24.两两交换链表中的节点

思路 定义一个指针cur, 先指向头节点&#xff0c; 1.判断后一个节点是否为空&#xff0c;不为空则交换值&#xff0c; 2.指针向后走两次 代码 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}*…

Java_集合_双列集合_Map

第一章Map集合 Map是双列集合顶级接口 什么叫做双列集合:一个元素有两部分构成:key和value -> 键值对 1.1.HashMap 常用方法: V put(K key, V value) -> 添加元素,返回的是被替换的value值 V remove(Object key) ->根据key删除键值对,返回的是被删除的value…

Codeforces Round 975 (Div. 1) D. Max Plus Min Plus Size(思维题 并查集/动态dp 线段树维护状态合并)

题目 思路来源 hhoppitree代码 官方题解 题解 注意到最大值一定会被取到&#xff0c; 对于最小值固定的话&#xff0c;对于1 2 3 4 5的连续段&#xff0c;要么贪心地取1 3 5&#xff0c;要么取2 4 如果最大值被包含在1 3 5里显然取1 3 5&#xff0c;否则换成2 4一定能取到…

亚马逊爆款三明治封口器发明专利维权,恐涉及大量卖家,速查

案件基本情况&#xff1a;起诉时间&#xff1a;2024-9-18案件号&#xff1a;2024-cv-08606原告&#xff1a;Jetteo, LLC原告律所&#xff1a;AVEK IP, LLC起诉地&#xff1a;伊利诺伊州北部法院涉案商标/版权&#xff1a;原告品牌简介&#xff1a;Jetteo&#xff0c;LLC&#x…

蜂鸟bebirdt15、西圣find、泰视朗可视挖耳勺好用吗?测评数据对比看这里

可视挖耳勺在当下已经被广泛使用&#xff0c;不过对于新手来说&#xff0c;选择一款优质产品却并不容易。蜂鸟t15、西圣find、泰视朗可视挖耳勺好用吗&#xff1f;作为一个测评博主&#xff0c;近期有不少用户问我这个问题。 根据目前市场上可视挖耳勺的品牌情况来看&#xff0…

A股突破3000,连续大涨,公司国庆假放10天

关注▲洋洋科创星球▲一起成长&#xff01; 庆祝A股突破3000&#xff0c;连续大涨&#xff0c;也不知道老板抽了什么风&#xff0c;公司今天开始放国庆假了&#xff0c;连休10天&#xff0c;哈哈哈哈哈哈。 27号开始放国庆假&#xff0c;连休10&#xff0c;刺激。 中秋国庆这一…

【C++】继承,菱形继承,虚拟继承,组合详解

目录 1. 继承概念与定义 1.1 概念 1.2 定义 2. 父类与子类的赋值规则 3. 继承的作用域 4. 子类的默认成员函数 5. 继承与友元 6. 继承与静态成员 7. 菱形继承 7.1 继承关系 7.2 菱形继承的问题 7.3 虚拟继承 8. 继承与组合 1. 继承概念与定义 1.1 概念 1. 继承&a…

论文速递 | Management Science 8月文章合集

编者按 在本系列文章中&#xff0c;我们对顶刊《Management Science》于8月份发布文章中进行了精选&#xff08;共9篇&#xff09;&#xff0c;并总结其基本信息&#xff0c;旨在帮助读者快速洞察行业最新动态。 推荐文章1 ● 题目&#xff1a;Optimal Mechanism Design with …

红队信息搜集扫描使用

红队信息搜集扫描使用 红队行动中需要工具化一些常用攻击&#xff0c;所以学习一下 nmap 等的常规使用&#xff0c;提供灵感 nmap 帮助 nmap --help主机扫描 Scan and no port scan&#xff08;扫描但不端口扫描&#xff09;。-sn 在老版本中是 -sP&#xff0c;P的含义是 P…

基于SPI协议的Flash驱动控制

1、理论知识 SPI&#xff08;Serial Peripheral Interface&#xff0c;串行外围设备接口&#xff09;通讯协议&#xff0c;是Motorola公司提出的一种同步串行接口技术&#xff0c;是一种高速、全双工、同步通信总线&#xff0c;在芯片中只占用四根管脚用来控制及数据传输&#…

【Python】利用Python+thinker实现旋转转盘

需求/目的&#xff1a;用Pythonthinker实现转盘&#xff0c;并且能够随机旋转任意角度。 转盘形式&#xff1a; 主界面&#xff1a; from tkinter import *winTk() win.title("大转盘") win.geometry("300x400")win.mainloop() 转盘绘制&#xff1a; 这…

USMART调试组件学习

USMART调试组件学习日记 写于2024/9/24日晚 文章目录 USMART调试组件学习日记1. 简介2. 调试组件组成3.程序流程图4. 移植解析5. 实验效果5. 实验效果 1. 简介 USMART 是由正点原子开发的一个灵巧的串口调试互交组件&#xff0c;通过它你可以通过串口助手调用程序里面的任何函…