Nagle算法
Nagle算法简介
Nagle算法主要是避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。
在默认的情况下,Nagle算法是默认开启的,Nagle算法比较适用于发送方发送大批量的小数据,并且接收方作出及时回应的场合,这样可以降低包的传输个数。
但是如果你的程序是 write-write-read 模式,在使用了Nagle算法后,第二个 write 就会被推后一个RRT发送而造成一个很长的ack等待,从而产生一个延迟。为了避免这种情况,一般建议在应用层做缓冲,将两个write合在一起,成为 write-read。
代码分析
我们通过一个例子观察下Nagle算法的延迟
- 服务器端代码:recipes/tpc/nodelay_server.cc
- 客户端代码:recipes/tpc/nodelay.cc
客户端代码
// ...... 仅展示出部分代码if (tcpnodelay){// 设置tcp TCP_NODELAYstream->setTcpNoDelay(true);printf("connected, set TCP_NODELAY\n");}else{stream->setTcpNoDelay(false);printf("connected\n");}for (int n = 0; n < num; ++n){printf("Request no. %d, sending %d bytes\n", n, len);if (buffering){std::vector<char> message(len + sizeof len, 'S');memcpy(message.data(), &len, sizeof len);int nw = stream->sendAll(message.data(), message.size());printf("%.6f sent %d bytes\n", now(), nw);}else{// 先发送头 在发送数据 验证Nagel算法stream->sendAll(&len, sizeof len);printf("%.6f sent header\n", now());usleep(1000); // prevent kernel merging TCP segmentsstd::string payload(len, 'S');int nw = stream->sendAll(payload.data(), payload.size());printf("%.6f sent %d bytes\n", now(), nw);}}
上面可以看出,正常下我们开启Nagel,并发送header和data两个数据包,我们还可以合并header和data,将其合成一个包发送,此外,我们还可以设置TCP_NODELAY选项。
测试
环境:两台桥联的虚拟机
我们使用ping命令测试一下两台机器正常情况下的延迟
wang@localhost tpc]$ ping 192.168.1.104
PING 192.168.1.104 (192.168.1.104) 56(84) bytes of data.
64 bytes from 192.168.1.104: icmp_seq=1 ttl=64 time=4.30 ms
64 bytes from 192.168.1.104: icmp_seq=2 ttl=64 time=4.08 ms
64 bytes from 192.168.1.104: icmp_seq=3 ttl=64 time=4.26 ms
64 bytes from 192.168.1.104: icmp_seq=4 ttl=64 time=3.06 ms
64 bytes from 192.168.1.104: icmp_seq=5 ttl=64 time=3.77 ms
^C
--- 192.168.1.104 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4016ms
rtt min/avg/max/mdev = 3.064/3.900/4.307/0.459 ms
大概在4ms左右
开启Nagle发送两个数据包
[wang@localhost tpc]$ ./nodelay 192.168.1.104 3210
connecting to 192.168.1.104:3210
connected
Request no. 0, sending 3210 bytes
1715777496.470708 sent header
1715777496.478341 sent 3210 bytes
Sent all 1 requests, receiving responses.
1715777496.483114 received 4 bytes, ack = 3210
total 0.013132 seconds
大概在13ms左右
关闭Nagle发送两个数据包
[wang@localhost tpc]$ ./nodelay -D 192.168.1.104 3210
connecting to 192.168.1.104:3210
connected, set TCP_NODELAY
Request no. 0, sending 3210 bytes
1715777794.851212 sent header
1715777794.855121 sent 3210 bytes
Sent all 1 requests, receiving responses.
1715777794.856854 received 4 bytes, ack = 3210
total 0.006093 seconds
可以看见,关闭Nagel后,延迟大约6ms左右
开启Nagel合并发送一个数据包
[wang@localhost tpc]$ ./nodelay -b 192.168.1.104 3210
connecting to 192.168.1.104:3210
connected
Request no. 0, sending 3210 bytes
1715778177.438170 sent 3214 bytes
Sent all 1 requests, receiving responses.
1715778177.441433 received 4 bytes, ack = 3210
total 0.004178 seconds
因为只发送一个,延迟跟ping差不多,大概4ms左右
相关文章:

Nagle算法
Nagle算法简介 Nagle算法主要是避免发送小的数据包,要求TCP连接上最多只能有一个未被确认的小分组,在该分组的确认到达之前不能发送其他的小分组。 在默认的情况下,Nagle算法是默认开启的,Nagle算法比较适用于发送方发送大批量的小数据&…...

MPLS小实验
实验图: 实验要求: 要求使用MPLS技术,将实验通,并在实验结束后使用命令:tracert -v -a 看是否基于标签进行转发。 如上:在每台路由器上都有两个环回,一个用于模拟用户网段,一个用于M…...

MongoDB聚合运算符:$week
MongoDB聚合运算符:$week 文章目录 MongoDB聚合运算符:$week语法使用举例 $week聚合运算符返回指定日期日期为一年中第几周的数字值为0到53之间。周从周日开始,第1周从一年的第一个周日开始。一年中第一个星期日之前的日期为第0周。这和 str…...

【Linux】如何定位客户端程序的问题
文章目录 1 客户端程序和服务端程序的差别2 问题类型2.1 崩溃(crash)2.2 CPU高2.3 内存高2.4 线程卡死 3 总结 1 客户端程序和服务端程序的差别 客户端程序是运行在终端上,通常都会与业务系统共存,而服务端程序通常会运行在单独的节点上,或者…...

AI学习指南数学工具篇-PCA基础知识
AI学习指南数学工具篇-PCA基础知识 1. PCA是什么? PCA,即主成分分析(Principal Component Analysis),是一种常用的数据降维技术。它通过线性变换将原始数据投影到一个新的坐标系中,旨在找到数据中的“主成…...

《系统架构设计师教程(第2版)》第4章-信息安全技术基础知识-02-信息加密技术
文章目录 1. 信息加密技术1.1 数据加密1.2 对称密钥加密算法1)数据加密标准(DES)2)三重DES(Triple-DES)3)国际数据加密算法(IDEA)4)高级加密标准(AES…...

Leetcode 404:左叶子之和
给定二叉树的根节点 root ,返回所有左叶子之和。 思路:遍历树,寻找左叶子节点; 如果判断是左叶子节点,就更新sum。 public static int sumOfLeftLeaves(TreeNode root){int sum0;sumcompute(root,sum);return sum;}/…...

Keil问题解决:结构体数组初始化,初始化后的值不是目标值
省流:使用的编译器为compiler version 6,切换为compiler version 5 如果缺少编译器,请参考:Keil手动安装编译器V5版本 结构体定义: typedef struct _TASK_COMPONENTS {uint8_t Run; // 程序运行标…...

C++set关联式容器
Cset 1. 关联式容器 vector、list、deque、forward_list(C11)等STL容器,其底层为线性序列的数据结构,里面存储的是元素本身,这样的容器被统称为序列式容器。而map、set是一种关联式容器,关联式容器也是用来存储数据的࿰…...

Celery Redis 集群版连接和PyCharm启动配置
目录 使用Redis cluster版作为broker原因 PyCharm配置 使用Redis cluster版作为broker 在celery5及其之前版本,需要配置如下才可行 celery_app.conf.update( broker_transport_options{“global_keyprefix”: “{celery}:”}, ) 原因 https://github.com/celery/…...

「AIGC算法」readLink实现url识别pdf、网页标题和内容
本文主要介绍AIGC算法,readLink实现url识别pdf、html标题和内容 一、设计思路 识别url是pdf或者网页网页处理逻辑,使用cheerio解析网页PDF处理逻辑,使用pdf-parse解析PDF文件自定义的函数来提取标题和内容二、可执行核心代码 const express = require("express")…...

Vue3+ts(day06:路由)
学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/frontlearningNotes 觉得有帮助的同学,可以点心心支持一下哈(笔记是根据b站上学习的尚硅谷的前端视频【张天禹老师】,记录一下学习笔记,用于自己复盘,有需要学…...

springboot集成dubbo实现微服务系统
目录 1.说明 2.示例 3.总结 1.说明 dubbo官网:https://cn.dubbo.apache.org/zh-cn/ Apache Dubbo 是一款 RPC 服务开发框架,用于解决微服务架构下的服务治理与通信问题,支持多种语言,官方提供了 Java、Golang 等多语言 SDK 实…...

idea使用gitee基本操作流程
1.首先,每次要写代码前,先切换到自己负责的分支 点击签出。 然后拉取一次远程master分支,保证得到的是最新的代码。 写完代码后,在左侧栏有提交按钮。 点击后,选择更新的文件,输入描述内容(必填…...

Docker容器里面有什么东西?
2024年5月15日,周三下午 Docker 容器内部包含了一个运行的应用程序及其依赖环境。当你创建一个 Docker 容器时,你可以指定容器应该运行哪个镜像。这个镜像是由一系列层组成的,每一层包含了一些文件和目录。当你运行这个镜像时,Doc…...

vue基础+高级用法
一、vue基础用法 mvvm的了解/认知 语义化模板mvc - model view controllermvvm - model view view-model vue是如何利用mvvm思想进行开发 双向数据绑定 花括号,构建了数据与视图的双向绑定通过视图绑定事件,来处理数据 生命周期-vue示例 建立&…...

鸿蒙应用布局ArkUI【基础运用案例】
布局基础运用案例 平级导航的复合网格视图 平级导航的复合网格视图常出现在同时展示多种不同内容的界面。 例如,市场类应用作为典型的平级导航,其首页不同板块采用了不同布局能力。 标题栏与搜索栏:因元素单一、位置固定在顶部,…...

GD32F103RCT6/GD32F303RCT6-UCOSIII底层移植(1)工程建立
本文章基于兆易创新GD32 MCU所提供的2.2.4版本库函数开发 后续项目主要在下面该专栏中发布: 手把手教你嵌入式国产化_不及你的温柔的博客-CSDN博客 感兴趣的点个关注收藏一下吧! 电机驱动开发可以跳转: 手把手教你嵌入式国产化-实战项目-无刷电机驱动&am…...

在本地设备上配置 Git 忽略特定文件
在本地设备上配置 Git 忽略特定文件 在日常的 Git 使用中,有时我们希望某些文件只在本地设备上被忽略,而不影响其他团队成员或设备。这篇博客将介绍如何在特定设备上配置 Git 忽略规则,使得一个文件不会被提交。 背景 通常,我们…...

cin.ignore()函数和stoll函数
cin.ignore()函数 cin.ignore() 是一个非常实用的函数,主要用于控制输入流 cin 的行为 cin.ignore(int n 1, char delimiter EOF); n:一个整数参数,表示要忽略的字符数量。默认值是1,意味着只忽略下一个字符。delimiter&#x…...

win11快速安装mysql数据库系统
win11快速安装mysql数据库系统 1、下载 1.1 打开官网 1.2 向下滚动页面 1.3 进入下载选项 1.4 下载8.0.4 LTS 1.5 开始下载 1.6 下载中 2、解压 大家注意,此时解压后目录是没有data目录的。 3、数据库初始化 3.1 管理员身份打开CMD 开始菜单上,输入…...

C# WinForm —— 21 RichTextBox 使用
1. 加载文件到控件中 加载文件时,要设置文件的路径和类型RichTextBoxStreamType,文件类型包含: RichText 0:富文本格式(RTF)流PlainText 1:纯文本流对象链接和嵌入(OLEÿ…...

【数据结构】堆(超详细)
文章目录 前言堆的概念及结构堆的实现堆的向下调整算法(建小堆为例)堆的向上调整算法(建小堆为例)堆的初始化销毁堆堆的插入堆的删除(规定删堆顶的数据)取堆顶元素判断堆是否为空获取堆的个数 完整代码(包括测试代码&a…...

常用正则 JS 持续更新
应用版本号正则验证 正则判断版本号(如:1.2.3 或 1.2.3.4),不允许出现 0.x.x;01.x.x; x.0x.x; x.00.x; x.x.00; x.x.0x/ ^ ([ 1-9 ] \d | [ 1-9 ])( . ([ 1-9 ] \d | \d )) {2,3} $ /0-10 保留一位小数的数…...

YOLO v6 iou_loss dfl_loss一直为0
Question img record infomation path is:…/mydata/images.train_cache.json Train: Final numbers of valid images: 1248/ labels: 1248. 0.1s for dataset initialization. img record infomation path is:…/mydata/images.val_cache.json Convert to COCO format 100%|█…...

FreeRTOS【4】线程挂起和恢复
1.开发背景 基于上一篇指引,成功创建并启动线程后,线程已经开始运行了,但是有时我们需要线程暂停运行,例如某个线程是控制 LED 闪灯的,如果现在需要让 LED 停止工作,单纯的关闭 LED 是没用的,因…...

CPU占用率过高排查
CPU占用率高是设备本身的一种现象,直观表现为display cpu-usage命令查询结果中整机CPU占用率“CPU usage”偏高,如超过70%。在网络运行中CPU高常常会导致其他业务异常,如BGP震荡、VRRP频繁切换、甚至设备无法登录。 通常,整机CPU占…...

关于 vs2019 c++20 规范里的 STL 库里模板 decay_t<T>
(1) 这个模板,在库代码里非常常见。 decay 英文是“衰弱,消减” 的意思,大概能感觉到就是要简化模板参数 T 的类型,去掉其上的修饰符。因为常用且复杂,故单独列出其源码和注释。先举例其应用场景…...

android C++打印堆栈
Android在Java层打印堆栈比较方便,代码如下: try {throw new Exception("Debug xxx call stack"); }catch(Exception e) {e.printStackTrace(); }但是在C模块中能打印调用堆栈吗?怎么打印调用栈呢? 答案是肯定的&…...

MySQL Undo Log、Redo Log、bin Log
Undo Log 回滚日志,用于将数据回滚到之前的状态。 MySQL在进行数据的增、删、改时,会将数据写入到Undo Log日志中。 对于Undo Log存在着insert和update两种类型的数据。插入语句对应的是insert类型,修改、删除语句对应的是update类型。 U…...