TCP发送优化(ZeroWindow分析)

通信模型一:

Client 创建一个 TCP 的 socket,并通过 SO_SNDBUF 选项设置它的发送缓冲区大小为 2048Byte,连接到 Server 后,每 1 秒发送一个 TCP报文(1024Byte)。Server 端不调用 recv()。预期的结果则分为以下几个阶段:

阶段1:Server 端的 socket 接收缓冲区未满,所以尽管 Server 不会 recv(),但依然能对 Client 发出的报文回复 ACK;

阶段2: Server 端的 socket 接收缓冲区被填满了,向 Client 端通告零窗口(Zero Window)。Client 端待发送的数据开始累积在 socket 的发送缓冲区;

阶段3: Client 端的 socket 的发送缓冲区满了,用户进程阻塞在 send函数里。

实际执行时,表现出来的现象也"基本"符合预期。不过当我们在 Client 端通过 netstat -an 监控 TCP 连接的发送队列长度时,发现这个值竟然从 0 最终增长到 14480,它轻松地超了之前设置的 SO_SNDBUF 值(2048)

分析

以上就是一个简单的Zero Window产生的模型,简单来说,Zero Window问题就是指在TCP连接中,发送方为了保障可靠传输,会根据接收方反馈的窗口大小来控制发送窗口的大小,但当接收方窗口大小为0时,发送方就会停止发送,从而导致通讯阻断的问题。所以起解决办法有以下几种。

一、增加接收方窗口大小

一种常用的方法是增加接收方的窗口大小。这样可以使得接收方有更多的缓存空间,从而避免出现Zero Window的情况。可以通过修改TCP接收缓冲区大小的方法来解决

int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int buf_size = 1024 * 1024 * 5; //设置缓存区大小为5MB
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof(buf_size));

二、禁用Nagle算法(默认是打开的)

Nagle算法是一种优化TCP传输的算法,其原理是将小的数据包合并成一个大的数据包再发送,从而减少网络传输量。但是当数据量很小的时候,会导致数据包积压,造成Zero Window问题。可以通过禁用Nagle算法来解决,示例代码如下:

int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int enable = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable));

三、增加发送方的等待时间

在一些情况下,由于网络状况不良,导致接收方没有足够的时间处理数据,造成Zero Window的情况。可以通过增加发送方的等待时间,等待接收方处理完成后再发送数据,从而避免出现Zero Window的情况,示例代码如下:

int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
struct timeval timeout;
timeout.tv_sec = 0; 
timeout.tv_usec = 500*1000; //等500毫秒
setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));

四、增加发送方的重传次数

在一些情况下,由于网络状况不良或者其他原因,导致数据丢失或者接收方无法正确接收数据,造成Zero Window的情况。可以通过增加发送方的重传次数,保证数据能够正确传输,从而避免出现Zero Window的情况,示例代码如下:

int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int retry_count = 6; //最多重试6次
setsockopt(sock, SOL_TCP, TCP_SYNCNT, (void*)&retry_count, sizeof(retry_count));

五、使用TCP Keepalive机制

TCP Keepalive机制是一种保持TCP连接的机制,其原理是在TCP连接空闲一段时间后,会向对端发送心跳包,以检测连接是否还存活。可以通过使用TCP Keepalive机制来避免出现Zero Window的情况,示例代码如下:

int sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
int enable = 1; //开启TCP Keepalive机制
setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void*)&enable, sizeof(enable));

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

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

相关文章

Hive数学函数讲解

Hive 是一个基于 Hadoop 的数据仓库工具,它支持类似于 SQL 的查询语言 HiveQL,并且提供了许多内建的数学函数来处理数值数据。下面我将逐一讲解您提到的这些数学函数,并提供一些使用案例和注意事项。 ROUND() 功能:四舍五入到指定…

【小白向】MMDeploy安装部署|暗坑标注版

文章目录 序言正文1 安装PPLCV2 TensorRT环境相关3 编译MMDeploy4 编译SDK结束 序言 本文主要针对在编译安装OpenMMLab团队的MMDeploy模型部署工具时遇到的“难以下手”的问题。 由于OpenMMLab的用户中很大一部分都是具有快速开发需求的人,或者说其实相当部分OpenM…

c语言算法——大数相加

C数据类型 类型与描述1基本数据类型 它们是算术类型,包括整型(int)、字符型(char)、浮点型(float)和双精度浮点型(double)。2枚举类型: 它们也是算术类型&am…

【docker】之基础篇二

目录 一、docker的数据管理1、数据卷2、数据卷容器: 二、端口映射与容器互联容器之间的通信 三、Docker查看日志四、Dockerfile定制镜像1、DockerFile常用的命令2、DockerFile实操 一、docker的数据管理 在生产环境中使用docker,需要对数据进行持久化&a…

R语言的ggplot2绘制分组折线图?

R绘制分组折线图.R 首先看数据情况:group有3组。Time有3组,数据意思是在3组3个时间点测量了某指标,现在要绘制组1、组2、组3某指标y按时间的变化趋势 数据情况: 看看最终的效果图如下: 下面是本次使用的代码 .libPat…

OpenHarmony 应用开发入门 (二、应用程序包结构理解及Ability的跳转,与Android的对比)

在进行应用开发前,对程序的目录及包结构的理解是有必要的。如果之前有过android开发经验的,会发现OpenHarmony的应用开发也很简单,有很多概念是相似的。下面对比android分析总结下鸿蒙的应用程序包结构,以及鸿蒙对比android的诸多…

Spring第七天(AOP)

简介 AOP(Aspect Oriented Programing)面向切面编程,一种编程范式,指导开发者如何组织程序结构 作用 在不惊动原始设计的基础上为其进行功能增强 Spring理念:无入侵式/无侵入式 基本概念 连接点(JoinPoint) : 程序执行过程中的任意位置&a…

ros2学习笔记-CLI工具,记录命令对应操作。

目录 环境变量turtlesim和rqt以初始状态打开rqt node启动节点查看节点列表查看节点更多信息命令行参数 --ros-args topic话题列表话题类型话题列表,附加话题类型根据类型查找话题名查看话题发布的数据查看话题的详细信息查看类型的详细信息给话题发布消息&#xff0…

html Canvas粒子文字特效

代码有点长&#xff0c;下面是代码&#xff1a; <!DOCTYPE html> <html><head><meta charset"UTF-8"><title>HTML5 Canvas粒子效果文字动画特效DEMO演示</title><link rel"stylesheet" href"css/normalize.c…

Bit.Store 加密卡集成主流 BRC20通证,助力 BTC 生态流动性

“Bit.Store 首创性的将包括 ORDI、SATS、以及 RATS 在内的主流 BRC20 资产集成到其加密卡支付中&#xff0c;通过以其推出的加密银行卡为媒介&#xff0c;助力 BTC 生态 Token 的流动性与消费。” 比特币网络在被设计之初&#xff0c;就是以一种去中心化、点对点的现金系统为定…

shardingsphere 出现 Cannot support database type ‘MySQL‘

场景 近日一个项目使用了shardingsphere后出现 java.lang.UnsupportedOperationException: Cannot support database type MySQL , 重点是在dev-pre环境中无法出现这个问题&#xff0c;而是在prod环境中会发生&#xff0c;且prod也不是100%发生&#xff0c; 当流量过大时会发…

js-cookie的使用--token的数据实现持久化

1.下载 npm install js-cookie 2.引入 import Cookies from "js-cookie"; 3.使用 // 写入cookie Cookies.set(name, value) // 读取 Cookies.get(name) // > value Cookies.get(nothing) // > undefined // 读取所有可见的cookie Cookies.get() // 删除某项co…

Vue2:全局事件总线

一、场景描述 之前我们学习了&#xff0c;通过props实现父子组件之间的通信。通过自定义组件&#xff0c;实现了子给父传递数据。 那么&#xff0c;兄弟关系的组件&#xff0c;如何通信了&#xff1f;任意组件间如何通信了&#xff1f; 这个时候&#xff0c;就要学习全局事件总…

JavaScript快速入门一

概述 JavaScript ECMAScript JavaScript特有的东西(BOM DOM) ECMAScript&#xff1a;客户端脚本语言&#xff0c;是欧洲计算机制造商协会ECMA&#xff0c;制定的标准&#xff0c;统一了所有客户端脚本语言的编码方式BOM&#xff1a;Browser Object Model&#xff0c;浏览器…

C#调用C动态链接库

前言 已经没写过博客好久了&#xff0c;上一篇还是1年半前写的LTE Gold序列学习笔记&#xff0c;因为工作是做通信协议的&#xff0c;然后因为大学时没好好学习专业课&#xff0c;现在理论还不扎实&#xff0c;不敢瞎写&#xff1b; 因为工作原因&#xff0c;经常需要分析一些字…

Gin之gin介绍和安装

1、gin介绍 1.1 gin 是什么&#xff1f; Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架&#xff0c;由于 httprouter&#xff0c;速度提高了近 40 倍。如果你需要极好的性能&#xff0c;使用 Gin 吧。 https://githu…

Unity-Arduino Bluetooth Plugin蓝牙插件使用时需要注意的一些事项(附插件下载链接)

一些参考链接 1.Android 无法扫描蓝牙设备踩坑 2.权限相关 1-首先要明确你的蓝牙设备是经典蓝牙还是低功耗&#xff08;BLE)蓝牙&#xff1a; 转载&#xff1a;Android蓝牙开发—经典蓝牙和BLE&#xff08;低功耗&#xff09;蓝牙的区别 2.如果是BLE蓝牙&#xff0c;需要打勾…

display布局实现一侧的盒子高度与另一侧盒子的高度等高

实现两边容器的高度等高主要是用 align-items: stretch 这个属性 stretch 拉伸: 子元素没有高度或高度为auto&#xff0c;将占满整个容器的高度 <template><div><h3>我是测试页面</h3><div class"container"><div class"left-…

原码,补码的除法

目录 一.原码的除法 &#xff08;1&#xff09;恢复余数法 重点看这 &#xff08;2&#xff09;不恢复余数法&#xff08;加减交替法&#xff09; 重点看这 二. 补码除法运算 重点看这 我们已经学习了如何进行原码&#xff0c;补码的乘法&#xff1a; http://t.csdnimg…

RibbonGroup 添加QAction下拉带Menu

实现代码如下所示&#xff1a; { QMenu* pMenu new QMenu(this); pMenu->addAction(QIcon(":/QRibbonDemo/res/smallpaste.png"), tr("Menu1")); pMenu->addAction(QIcon(":/QRibbonDemo/res…