《TCP/IP详解 卷一》第15章 TCP数据流与窗口管理
目录
15.1 引言
15.2 交互式通信
15.3 延时确认
15.4 Nagle 算法
15.4.1 延时ACK与Nagle算法结合
15.4.2 禁用Nagle算法
15.5 流量控制与窗口管理
15.5.1 滑动窗口
15.5.2 零窗口与TCP持续计时器
15.5.3 糊涂窗口综合征
15.5.4 大容量缓存与自动调优
15.6 紧急机制
15.7与窗口管理相关的攻击
15.8总结
15.1 引言
两类TCP传输:
交互式传输:
单个报文小,如ssh,网络游戏中账号信息,鼠标操作等信息。
批量传输:
即大量数据传输。如文件共享下载,web访问。
需流量控制,防止接收端溢出。
15.2 交互式通信
网络中大部分是大批量传输,少部分是交互式传输。
ssh是典型交互式数据。
特点:小包。
ssh每个输入一个字符会生成4个TCP数据段:
1. 客户端指令输入
2. 服务器ACK
3. 服务器执行结果
4. 客户端ACK
其中2,3可合并一起发送,即ACK报文携带回显数据,这叫延迟ACK。
TCP段PSH标志含义:
表示发送端没有其他数据需要传输。而接收端收到数据后应立即传递给应用层。
因为SSH客户端产生的都是短小信息,通常SSH TCP报文都带PSH标志。
15.3 延时确认
延迟ACK:
TCP不会对收到的每个数据都回复一个ACK,而是通过累积ACK后将延迟的ACK和后续需要传的数据结合发送。
常用于批量数据传输中。
好处:减少ACK数目,减轻网络负载。
而快速ACK,即每个报文都会回复一个ACK。
15.4 Nagle 算法
SSH客户端一个单击动作会产生四个TCP报文,其中包含TCP头,IP头等开销,代价很高,会加重广域网阻塞。
解决方法:Nagle算法
Nagle翻译:突然
Nagle原理:
若发送端没有收到所有数据的ACK时,不发送小报文。直到所有在传数据收到ACK,在这个等待期间会整合多个小数据,通过一个更大报文发送。
所以ACK返回越快,数据发送越快。
优点:在高延迟网络中可整合小数据,减少小包数目。
缺点:增加了时延。
Nagle算法适用场景:
频繁传输小数据块,并延迟不敏感。
15.4.1 延时ACK与Nagle算法结合
延时ACK:延迟发送ACK,用于减少ACK包的数量,降低网络开销。
Nagle算法:等待收到所有已发送数据的ACK后,期间合并小包成大包再发送数据。
所以可知,两者结合使用导致短暂死锁。
所以如果SSH服务器开启了延迟ACK功能,客户端最好禁用Nagle。
15.4.2 禁用Nagle算法
Nagle算法增加了时延,对实时应用不适合。
如SSH,实时网络游戏。
内核协议栈禁用Nagle:
net.ipv4.tcp_no_delay = 1
应用程序禁用:
设置socket TCP_NODELAY选项
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, (void *)&flag, sizeof(int))
15.5 流量控制与窗口管理
每个TCP报文段包含:序列号,ACK号,窗口大小。
ACK号:下一次期待收到的报文序列号,说明之前的数据已全部接收。
窗口大小:向对方指示,自己的接收缓冲区还剩多少空间。
15.5.1 滑动窗口
每对TCP连接的两端都维护一个发送窗口和接收窗口。
其中发送窗口大小由对端的接收窗口通告。
在没收到数据的ACK情况下,最多可发送的数据量就是发送窗口大小。
滑动窗口作用:
优化网络利用率:
滑动窗口允许发送方连续发送多个数据段而不必等待每个数据段ACK。提高网络利用率。
避免拥塞:
发送方根据接收方通告的窗口大小来控制发送量,避免发送过快而引起拥塞。
发送窗口:
一旦收到已发送数据的ACK后,就移动窗口,可继续发送更多数据。
接收窗口:
把接收窗口值给通告给发送方。
收到数据的序列号小于左边界RCV.NXT,就是重复报文,丢弃数据。
收到数据的序列号大于右左边界RCV.NXT+RCV.WND,超出处理范围,丢弃数据。
15.5.2 零窗口与TCP持续计时器
TCP通过接收端的窗口通告实现流量控制。指示接收端缓冲区可接收数量。
通告的接收窗口为0时,可阻止对方发送。
接收端缓冲区重新有可用空间时,可传输一个窗口更新给发送端。该窗口更新是一个纯ACK,不包含数据。
问题:
如果接收端的窗口更新报文丢失,而发送方需要等到窗口更新报文才可继续发送。造成死锁。
解决方法:
周期向接收端查询窗口值,即发送窗口探测,接收端回复一个ACK报文,其中包含窗口大小。
TCP报文是纯ACK,则不会重传ACK。
TCP报文不是纯ACK,会重传ACK和数据。
15.5.3 糊涂窗口综合征
糊涂窗口综合征SWS
出现原因有:
接收端没等到窗口变大就通告,导致通告的窗口小。
发送端没等到将小数据合成更大报文就方法,导致发送数据小。
坏处:
传输的TCP数据很小。传输效率低。
解决方法:
接收端不通告小窗口值。
发送端不发送小报文段,由Nagle控制如何发送。
15.5.4 大容量缓存与自动调优
不必提前设置一个过大发送/接收缓存。而是根据待传数据大小,不断估算缓存大小,不断通告窗口大小。
即窗口自动调优。
如何设置窗口的自动调优范围:
接收窗口:
net.ipv4.tcp_rmem= 4096 87380 174760
发送窗口:
net.ipv4.tcp_wmem= 4096 87380 174760
上述三个值分别是最小值,默认值,最大值。
最小值:
应用程序设置发送缓冲区小于最小值时,内核自动扩大到最小值,如4096。
默认值:
应用程序未指定发送缓冲区大小时,内核会使用这个默认值。
最大值:
应用程序不能设置发送缓冲区的大小超过最大值。
自动调优:
当接收端根据接收缓存区剩余大小,动态发送窗口更新报文给发送端,控制发送端发送速率。
若TCP的接收缓存区太小,会严重限制TCP吞吐量。
小结:接收窗口和发送窗口值会根据网络环境和系统配置而动态调整,通常范围为几KB到几MB。
15.6 紧急机制
TCP URG标志:
指示该TCP报文包含紧急数据。
MSG_OOB标志可发送接收带外数据。
带外数据:使用带外(额外)通道来传输数据,可不受滑动窗口控制,实现传输紧急数据。
MSG_OOB使用方法如:
send(socket_fd, buff, buff_len, MSG_OOB);
recv(socket_fd, buffer, MAX_BUFFER_SIZE, MSG_OOB);
MSG_OOB数据比普通数据有更高优先级。
15.7与窗口管理相关的攻击
通告非常小的窗口,让发送方缓慢发送,并保持忙碌发送,耗尽资源。
15.8总结
延迟ACK:
使用场景:交互式通信中,当接收方收到数据后,延迟回复ACK,等到有数据发送时再一起携带ACK发送。
优点:减少包数量。
缺点:延时增大。
Nagle算法:
使用场景:广域网中RTT较大的环境中,采用Nagle算法,可以合并多个小数据包成一个,再发送。
优点:减少包数量,降低传输开销。
缺点:延时增大。
延迟ACK和Nagle算法会短暂死锁,有的会禁用Nagle算法。
通常延时不敏感的交互式应用可使用Nagle。
当接收端的接收缓存为空,会通告窗口为0。此时发送端会停止发送,并周期发送窗口探测,直到通告不为0。
糊涂窗口综合症:
接收端通告了小窗口,发送端立即发送小数据,导致网络太多小数据。
解决方法:
接收端不通告小窗口。
发送端不发送小数据。
相关文章:

《TCP/IP详解 卷一》第15章 TCP数据流与窗口管理
目录 15.1 引言 15.2 交互式通信 15.3 延时确认 15.4 Nagle 算法 15.4.1 延时ACK与Nagle算法结合 15.4.2 禁用Nagle算法 15.5 流量控制与窗口管理 15.5.1 滑动窗口 15.5.2 零窗口与TCP持续计时器 15.5.3 糊涂窗口综合征 15.5.4 大容量缓存与自动调优 15.6 紧急机制…...
ContentType类型总结
ContentType类型总结 Content-Type是一个HTTP头部字段,用于指示资源的媒体类型(MIME类型),以及可选的字符集和编码方式。它告诉浏览器或其他客户端如何解释接收到的数据。以下是一些常见的Content-Type类型及其用途: t…...

基于脚手架创建vue工程
环境要求: node.js:前端项目的运行环境 npm:javascript的包管理器 vue cli:项目脚手架 忘了自己有没有安装可以通过在黑窗口输入命令看一下 node -v npm -v 这里出现版本号就说明已经安装了 安装脚手架的命令:npm i vue/cli -g 创建vue基础工程 1.在一个没…...
【Http】OSI 和 TCP/IP,OSI,TCP/IP为什么网络要分层?
目录 OSI 和 TCP/IP OSI TCP/IP 为什么网络要分层? OSI 和 TCP/IP OSI 
STM32(5) GPIO(2)输出
1.点亮LED 1.1 推挽接法和开漏接法 要想点亮LED,有两种接法 推挽接法: 向寄存器写1,引脚输出高电平,LED点亮;向寄存器写0,引脚输出低电平,LED熄灭。 开漏接法: 向寄存器写0&…...

shell脚本一键部署docker
Docker介绍 Docker 是一个开源的平台,用于开发、交付和运行应用程序。它利用容器化技术,可以帮助开发人员更轻松地打包应用程序及其依赖项,并将其部署到任何环境中,无论是开发工作站、数据中心还是云中。以下是 Docker 的一些关键…...
vue2实现拖拽排序效果
1、首先下载 vuedraggable 插件 npm i -S vuedraggable2、使用方法 <template><div><div style"display: flex; justify-content: center; align-items: center"><div style"width: 120px; height: 60px; line-height: 60px; text-align…...
数据结构实验:二叉排序树
题目描述 对应给定的一个序列可以唯一确定一棵二叉排序树。然而,一棵给定的二叉排序树却可以由多种不同的序列得到。例如分别按照序列{3,1,4}和{3,4,1}插入初始为空的二叉排序树,都得到一样的结果。你的任务书对于输入的各种序列,判断它们是否…...
Java类加载流程?
Java类加载过程是指将.class文件中的字节码数据加载到内存中,并生成对应的Class对象的过程。Java类加载器(ClassLoader)负责执行这个任务。Java类加载过程主要包括以下几个步骤: 加载(Loading):…...
Docker从0到1的开始【入门篇】
Docker是一种流行的容器化平台,它允许开发人员将应用程序及其所有依赖项打包到一个标准化的单元中,从而实现快速部署和可移植性。在本文中,我们将列出一些常用的Docker命令,以帮助您更好地了解和使用Docker。 1. 安装Docker 要安…...

@ResponseStatus
目录 概述: 用途: 参数: 注意事项: 自定义异常类: 底层原理: 概述: 在 Spring MVC 中,我们有很多方法来设置 HTTP 响应的状态码其中最直接的方法:使用 ResponseSt…...

高效加载大文件(pandas+dask)
一、仅用pd加载大文件(iterator、chunksize) 要使用Pandas进行高效加载超大文件,我们通常会利用其内置的分块(chunk)处理功能。不过,请注意,Pandas本身并不支持多线程读取文件;它更倾向于单线程中进行块处理…...

游戏引擎分层简介
游戏引擎分层架构(自上而下) 工具层(Tool Layer) 在一个现代游戏引擎中,我们最先看到的可能不是复杂的代码,而是各种各样的编辑器,利用这些编辑器,我们可以制作设计关卡、角色、动画…...
向爬虫而生---Redis 探究篇6<Redis的Bigkey问题介绍>
前言: 随着数据规模的增长,Redis的BigKey问题也开始显现。 BigKey问题主要指的是存储了大量数据的key,这可能给Redis的性能和可用性带来负面影响。当一个key的数据量过大时,会占用宝贵的内存资源,拖慢Redis的响应速度。此外,存储和恢复这些BigKey也会变得困难和耗时,增…...

【开源物联网平台】FastBee认证方式和MQTT主题设计
🌈 个人主页:帐篷Li 🔥 系列专栏:FastBee物联网开源项目 💪🏻 专注于简单,易用,可拓展,低成本商业化的AIOT物联网解决方案 目录 一、接入步骤 1.1 设备认证 1.2 设备交…...
Ubuntu Qt控制终端运行ros
文章目录 gnome-terminalQt 通过QProcess类Qt 通过system gnome-terminal 在Ubuntu中可以使用man gnome-terminal命令查看gnome-terminal的使用指南,也可在ubuntu manuals查看: NAMEgnome-terminal — 一个终端仿真应用.概要gnome-terminal [-e, --c…...
mysql 性能调优参数配置文件
########################################################################### ## my.cnf for MySQL 8.0.x # ## 本配置参考 https://imysql.com/my-cnf-wizard.html # ## 注意: …...
windows右键新建文件没有txt文本文档怎么办?
我碰到此问题,按照以下方法改了注册表, 重启之后就正常了(没有注销,只是单纯重启)。以下方法来自AI: 如果在注册表的 .txt 路径下没有找到 ShellNew 键,你可以尝试手动创建这个键和所需的值来恢…...

已读不回,我又玻璃心了
最近有点上火,3个询盘给我整我无语了,难道我还没修炼到家?玻璃心又出来作祟了? 客户A急火火的发我一个文件,需求内容ios客户端调整,让我按照需求给找个人处理下,我收到后抓紧时间摇人࿰…...
面试经典150题(105-107)
leetcode 150道题 计划花两个月时候刷完之未完成后转,今天(第2天)完成了3道(105-107)150 105.(191. 位1的个数)题目描述: 编写一个函数,输入是一个无符号整数(以二进制串的形式&am…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

springboot 百货中心供应链管理系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,百货中心供应链管理系统被用户普遍使用,为方…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
django filter 统计数量 按属性去重
在Django中,如果你想要根据某个属性对查询集进行去重并统计数量,你可以使用values()方法配合annotate()方法来实现。这里有两种常见的方法来完成这个需求: 方法1:使用annotate()和Count 假设你有一个模型Item,并且你想…...

【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

2025季度云服务器排行榜
在全球云服务器市场,各厂商的排名和地位并非一成不变,而是由其独特的优势、战略布局和市场适应性共同决定的。以下是根据2025年市场趋势,对主要云服务器厂商在排行榜中占据重要位置的原因和优势进行深度分析: 一、全球“三巨头”…...
MySQL 8.0 事务全面讲解
以下是一个结合两次回答的 MySQL 8.0 事务全面讲解,涵盖了事务的核心概念、操作示例、失败回滚、隔离级别、事务性 DDL 和 XA 事务等内容,并修正了查看隔离级别的命令。 MySQL 8.0 事务全面讲解 一、事务的核心概念(ACID) 事务是…...