Linux网络编程: TCP协议之SACK与D-SACK详解

一、参考RFC

https://www.ietf.org/rfc/rfc2018
https://www.ietf.org/rfc/rfc2883.txt

二、SACK选项(RFC2018)

SACK实现的需要发送方和接收方协作。为此,TCP首部实际上定义了两种选项:SACK允许选项、SACK选项。

  • SACK允许选项,即Sack-Permitted选项,用于标识是否支持 SACK,是在 TCP 连接建立时发送。
  • SACK选项,则包含了具体的 SACK 信息。

当前所有操作系统都已经默认打开SACK支持了,但也有些系统需要协商。

2.1 Sack-Permitted 选项

也就是SACK允许选项,格式如下:

TCP Sack-Permitted Option:Kind: 4+---------+---------+
| Kind=4  | Length=2|
+---------+---------+

SACK_Permitted 选项,该选项只允许在 TCP 连接建立时,有SYN标志的包中设置,也即TCP握手的前两个包中,分别表示通信的两方各自是否支持SACK。

在Linux中可以查看/proc/sys/net/ipv4/tcp_sack文件是否默认打开SACK-Permitted。如果为1,默认打开,SYN包不会再发送这个选项来确认了。

$ cat /proc/sys/net/ipv4/tcp_sack 
1

wireshark抓包确认是在SYN包中存在
在这里插入图片描述

Linux 2.2之后默认打开Sack-Permitted,见
(default: enabled; since Linux 2.2) Enable RFC 2018 TCP Selective Acknowledgements
https://man7.org/linux/man-pages/man7/tcp.7.html

2.2 Sack选项

该选项参数告诉对方已经接收到并缓存的不连续的数据块,发送方可根据此信息检查究竟是哪些块丢失,从而发送相应的数据块。
由于整个TCP首部的选项部分不能超过40字节,所以一个ACK段中最多可以容纳4组SACK信息。

       TCP SACK Option:Kind: 5Length: Variable+--------+--------+| Kind=5 | Length |+--------+--------+--------+--------+|      Left Edge of 1st Block       |+--------+--------+--------+--------+|      Right Edge of 1st Block      |+--------+--------+--------+--------+|                                   |/            . . .                  /|                                   |+--------+--------+--------+--------+|      Left Edge of nth Block       |+--------+--------+--------+--------+|      Right Edge of nth Block      |+--------+--------+--------+--------+

Left Edge表示已收到的不连续块的第一个序号,Right Edge表示已收到的不连续块的最后一个序号+1,即左闭右开区间。通过ACK和SACK信息,发送方就可以确定接收方具体没有收到的数据就是从ACK到最大SACK信息之间的那些空洞的序号。

注意两个关键词:已收到不连续,SACK信息指明的区间数据已经收到了,不用再重传了。

注意:SACK会消费发送方的资源,试想,如果一个攻击者给数据发送方发一堆SACK的选项,这会导致发送方开始要重传甚至遍历已经发出的数据,这会消耗很多发送端的资源。

2.3 SACK使用示例

2.3.1 如果只有一个Block, 那么left edge应该比ack大

wireshark可以使用tcp.options.sack来过滤
在这里插入图片描述

2.3.2 如果有多个Block, 第一个block的范围不能被SACK的第二个block覆盖

wireshark可以使用tcp.options.sack.count > 1来过滤多个SACK Block的包
在这里插入图片描述

2.3.3 SACK在数据重传时候的应用

考虑有SACK包的一段TCP通信数据

在这里插入图片描述

要想接收5846这之前所有的数据,但是已经确认了4287之前的数据。还缺少[4287,5846) 这一段区间数据,但是这一段数据又已经有一部分发送成功了,还缺少[4287, 4330), [4910, 5185)这一部分数据。

在这里插入图片描述

如果双方都支持SACK选项,那么只需要发送[4287, 4330), [4910, 5185)这两段数据即可;如果不支持SACK选项,得必须重发[4287,5846)这一整段数据。

第一部分44字节,第二部分275字节。
在这里插入图片描述
在这里插入图片描述

44字节分了2个包发送。
在这里插入图片描述

又重传了[4910, 5185)这一部分数据。

对于区间重传的数据seq是可以直接填写的。

对于接收端来说,收到数据要有ACK
在这里插入图片描述

44字节接收完了,还缺275字节。
在这里插入图片描述

最终两部分缺失数据接收完毕。
在这里插入图片描述

结论:在重传数据的时候,可以根据SACK信息,只需要重传44+275字节,而不用重传5846-4287这一段数据了,节省流量。

三、D-SACK(RFC2883)

D-SACK,又叫duplicate-SACK。
RFC2883扩展了RFC2018对SACK选项的定义,来指示接收端收到了重复包(duplicate packet),并通知发送端。
RFC2883建议在收到重复报文的时候,SACK选项的第一个块(这个块也叫做D-SACK块)可以用来传递这个重复报文的信息。这样允许TCP发送端根据SACK选项来推测不必要的重传。进而利用这些信息在乱序传输的环境中执行更健壮的操作。

这个D-SACK扩展是与原有的SACK选项的实现相互兼容的。D-SACK的使用也不需要TCP连接的双方额外协商(只要之前协商了SACK选项即可)。当TCP的发送方不理解D-SACK扩展的时候会简单的丢弃D-SACK块并继续处理SACK选项中的其他块。

接收端每个重复包最多在一个D-SACK块中上报一次。如果接收端依次发送了两个带有相同D-SACK块信息的ACK报文,则表示接收端接收了两次重复包,因此带有D-SACK块信息的ACK确认包传输丢失的时候重复包信息也会丢失。

在linux中/proc/sys/net/ipv4/tcp_dsack控制发出的报文中是否携带DSACK信息,但是不管该参数设置为何值,对于接收的TCP报文,linux总是会执行D-SACK块的检测处理。当linux检测到D-SACK块信息的时候会尝试撤销拥塞控制对于拥塞窗口的作用。另外在TLP丢包探测中也可以用来做loss probe的丢包探测。

Linux 2.4开始默认支持D-SACK,见https://man7.org/linux/man-pages/man7/tcp.7.html

在这里插入图片描述

3.1 D-SACK的特点:

  1. 只能是第一个SACK block。即使SACK有多个block也只有第一个block能表示D-SACK,也就是说每个SACK选项中最多有一个D-SACK块。
  2. 如果SACK的第一个block的范围被ACK所覆盖,那么就是D-SACK
  3. 如果SACK的第一个block的范围被SACK的第二个block覆盖,那么就是D-SACK——相同也算是覆盖。

3.2 D-SACK的意义

可见,引入了D-SACK,有这么几个好处:

  • 可以让发送方知道,是发出去的包丢了,还是回来的ACK包丢了。
  • 是不是自己的timeout太小了,导致重传。
  • 网络上出现了先发的包后到的情况(又称reordering)
  • 网络上是不是把我的数据包给复制了。
  • 可以做拥塞控制。

3.3 抓包示例

接收端在接收到SACK报文的时候,应该把第一个SACK块与这个ACK报文的ack number比较(而不是和当前已经接收到的最大的ack number比较),如果小于等于ack number则说明是D-SACK块,如果大于ack number则应该与第二个SACK块比较。如果第二个SACK块包含第一个SACK块,则说明第一个SACK块为D-SACK块,如果上面两个条件都不满足说明第一个SACK块是普通的SACK块。

tcp.options.sack.dsack and tcp.options.sack.count > 1 过滤D-SACK组合情况

在这里插入图片描述

3.4 RFC示例

示例一:ACK丢包

下面的示例中,丢了两个ACK,所以,发送端重传了第一个数据包(3000-3499),于是接收端发现重复收到,于是回了一个SACK=3000-3500,因为ACK都到了4000意味着收到了4000之前的所有数据,所以这个SACK就是D-SACK——旨在告诉发送端我收到了重复的数据,而且我们的发送端还知道,数据包没有丢,丢的是ACK包。

Transmitted  Received    ACK Sent
Segment      Segment     (Including SACK Blocks)3000-3499    3000-3499   3500 (ACK dropped)
3500-3999    3500-3999   4000 (ACK dropped)
3000-3499    3000-3499   4000, SACK=3000-3500---------

示例二,网络延误

下面的示例中,网络包(1000-1499)被网络给延误了,导致发送方没有收到ACK,而后面到达的三个包触发了“Fast Retransmit算法”,所以重传,但重传时,被延误的包又到了,所以,回了一个SACK=1000-1500,因为ACK已到了3000,所以,这个SACK是D-SACK——标识收到了重复的包。

这个案例下,发送端知道之前因为“Fast Retransmit算法”触发的重传不是因为发出去的包丢了,也不是因为回应的ACK包丢了,而是因为网络延时了。

Transmitted    Received    ACK Sent
Segment        Segment     (Including SACK Blocks)500-999        500-999     1000
1000-1499      (delayed)
1500-1999      1500-1999   1000, SACK=1500-2000
2000-2499      2000-2499   1000, SACK=1500-2500
2500-2999      2500-2999   1000, SACK=1500-3000
1000-1499      1000-1499   30001000-1499   3000, SACK=1000-1500---------

还有比较多的例子,详细的可以参考 RFC2883。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

突破校园网限速:使用 iKuai 多拨分流负载均衡 + Clash 代理(内网带宽限制通用)

文章目录 1. 简介2. iKuai 部署2.1 安装 VMware2.2 安装 iKuai(1) 下载固件(2) 安装 iKuai 虚拟机(3) 配置 iKuai 虚拟机(4) 配置 iKuai(5) 配置多拨分流 2.3 测试速度 3. Clash 部署(1) 配置磁盘分区(2) 安装 Docker(3) 安装 Clash(4) 设置代理 4. 热点:一起瓜分互…

Redis基本概念

什么是Redis Redis(Remote Dictionary Server ),即远程字典服务,是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。 Redis的用处 缓存 缓存现在几…

shell脚本2

变量 变量是在程序中保存用户数据的一段内存存储空间,变量名是内存空间的首地址 字母、数字、下划线组成,不能以数字开头 原则:直接使用,不需要变量声明 格式:变量名 变量的值 环境变量 关闭窗口即会失效 若要永久生…

数据结构—红黑树

红黑树介绍 红黑树(Red Black Tree)是一种自平衡二叉查找树。由于其自平衡的特性,保证了最坏情形下在 O(logn) 时间复杂度内完成查找、增加、删除等操作,性能表现稳定。 在 JDK 中,TreeMap、TreeSet 以及 JDK1.8 的 …

数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成

数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成 目录 数据生成 | Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成生成效果基本描述模型描述程序设计参考资料 生成效果 基本描述 1.Matlab实现基于K-means和SVM的GMM高斯混合分布的数据生成&#xf…

深度学习实践(一)基于Transformer英译汉模型

本文目录 前述一、环境依赖二、数据准备1. 数据加载程序解析word_tokenize()将字符串分割为一个个的单词,并由列表保存。 2. 构建单词表程序解析(1)将列表里每个子列表的所有单词合并到一个新列表(没有子列表)中。&…

RabbitMQ3.13.0起支持MQTT5.0协议及MQTT5.0特性功能列表

RabbitMQ3.13.0起支持MQTT5.0协议及MQTT5.0特性功能列表 文章目录 RabbitMQ3.13.0起支持MQTT5.0协议及MQTT5.0特性功能列表1. MQTT概览2. MQTT 5.0 特性1. 特性概要2. Docker中安装RabbitMQ及启用MQTT5.0协议 3. MQTT 5.0 功能列表1. 消息过期1. 描述2. 举例3. 实现 2. 订阅标识…

浅聊java集合框架中的java.util.LinkedList

java集合框架总览 Java集合框架是一个用来代表和操纵集合的统一架构,它为管理和组织对象的集合提供了一组类和接口。这个框架包含三个主要部分:接口、实现和算法。 接口: Collection:这是集合框架的根接口,定义了集…

亚马逊运营必看!如何运用自养号测评获得买家评论转销量?

作为亚马逊卖家,相信大家对亚马逊的产品星级评分 (Rating) 都不陌生,这几颗亮眼的星星,不仅可以让你的Listing脱颖而出,获得足够多、足够高的产品评分,也是促使消费者下单的重要因素之一。 那么,亚马逊运营…

3D可视化技术亮相高铁站,引领智慧出行新潮流

在科技飞速发展的今天,我们的生活正经历着前所未有的变革。高铁站作为现代交通的重要枢纽,也在不断地创新和进步。 3D可视化技术通过三维立体的方式,将高铁站内部和外部的结构、设施、流线等以更加直观、生动的形式呈现出来。乘客们只需通过手…

全国高等学校sql

教育部颁发的最新高等学校名单,sql已整理好(按照省份树形结构),是mysql8版本的 全国高等学校:预览地址:https://kdocs.cn/l/ckaFzCWMV1jn sql下载地址: https://pan.imgbed.link/file/22581

mac/win使用pyinstaller打包app/exe文件,活着执行脚本,双击运行

🌸 踩坑记录 python环境最好使用虚拟环境,推荐使用conda管理,并且若本地有python环境,不要使用和 本地环境版本 相同的虚拟环境 这里踩坑较多,已经记不清楚注意点 虚拟环境python版本不要和本地环境一样 mac/win只能…

匿名信一封来信一封云来信表白祝福道歉短信H5公众号,小程序系统搭建(搭建赠送人工传话系统+主机管理面板)

“一封来信”是最近某音上爆火的一个活动话题,可以通过H5网站,编辑自己想要对某人说的话或者祝福,网站会把您想说的发给您预留的号码,可以特定时间,特定话题。 最近的兴起是给朋友或暗恋的人发送新年祝福,…

Leetcode算法训练日记 | day21

一、二叉搜索树的最小绝对差 1.题目 Leetcode:第 530 题 给你一个二叉搜索树的根节点 root ,返回 树中任意两不同节点值之间的最小差值 。 差值是一个正数,其数值等于两值之差的绝对值。 示例 1: 输入:root [4,2,…

『大模型笔记』LLMs入门:从头理解与编码LLM的自注意力机制

LLMs入门:从头理解与编码LLM的自注意力机制 这里直接引用我语雀上的的文章:《从头理解与编码LLM的自注意力机制》

python第四次作业

1、找出10000以内能被5或6整除,但不能被两者同时整除的数(函数) def func():for i in range(10001):if (i % 5 0 or i % 6 0) and i % 30 ! 0:print(i,end " ")func() 2、写一个方法,计算列表所有偶数下标元素的…

AWVS/Acunetix Premium V24.3.2403高级版漏洞扫描器

前言 Acunetix Premium 是一种 Web 应用程序安全解决方案,用于管理多个网站、Web 应用程序和 API 的安全。集成功能允许您自动化 DevOps 和问题管理基础架构。 Acunetix Premium:全面的 Web 应用程序安全解决方案 Web 应用程序对于企业和组织与客户、…

优先级队列

优先级队列的基本使用 模拟实现上面的接口函数&#xff0c;优先级队列不是队列&#xff0c;而是类似一个堆一样的东西&#xff0c;我们先来试试它的接口函数是怎么个样子的。 需要包含的头文件是queue。 #include<iostream> #include<queue> using namespace std;…

Qt Creator 新建项目

&#x1f40c;博主主页&#xff1a;&#x1f40c;​倔强的大蜗牛&#x1f40c;​ &#x1f4da;专栏分类&#xff1a;QT❤️感谢大家点赞&#x1f44d;收藏⭐评论✍️ 目录 一、使用 Qt Creator 新建项目 1、新建项目 2、选择项目模板 3、选择项目路径 4、选择构建系统 5…

基于达梦数据库开发-python篇

文章目录 前言一、搭建demo前提初始化简单demo 二、可能出现的异常情况DistutilsSetupErrorNo module named dmPythonlist报错 总结 前言 出于信创的考虑&#xff0c;近年来基于国产数据库达梦的应用开发逐渐变多。本文将介绍在windows环境下基于DM8版本的python的简单开发使用…