c++理论篇(一) ——浅谈tcp缓存与tcp的分包与粘包

介绍

在网络通讯中,Linux系统为每一个socket创建了接收缓冲区与发送缓冲区,对于TCP协议来说,这两个缓冲区是必须的.应用程序在调用send/recv函数时,Linux内核会把数据从应用进程拷贝到socket的发送缓冲区中,应用程序在调用recv/read函数时,内核把接收缓冲区中的数据拷贝到应用进程的接收缓冲区中.
在这里插入图片描述

我们也可以查看socke缓冲区的大小:

int bufsize=0;
socket_t optlen=sizeof(bufsize);
getsockopt(sockfd,SOL_SOCKET,SO_SNDBUF,&bufsize,(socklen_t*)&optlen); //获取发送缓冲区大小
cout<<"send buffer size:"<<bufsize<<endl; //打印getsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&bufsize,(socklen_t*)&optlen); //获取接收缓冲区大小
cout<<"recv buffer size:"<<bufsize<<endl; //打印

一些思考

  1. send函数会阻塞吗
    会,如果发送端的发送缓冲区与接收端的接收缓冲区已满,那么send函数会阻塞,直到缓冲区有空闲位置。

  2. 向socket发送数据后,如果关闭socket,对端会接收到数据吗
    会,因为socket缓冲区是双向的,发送端和接收端都会缓冲数据

Nagle算法

前言

在TCP协议中,无论发送多少数据,都要在数据前面加上协议头,同时,对方收到数据后,也需要回复ACK表示确认。为了尽可能的利用网络带宽,TCP希望每次都能够以MSS(Maximum Segment Size,最大报文长度)的数据块来发送数据。

Nagle算法的目的

Nagle算法就是为了尽可能发送大块的数据,避免网络中充斥着小数据块。

Nagle算法的工作原理

Nagle算法的定义是:任意时刻,最多只能有一个未被确认的小段,小段是指小于MSS的数据块,未被确认是指一个数据块发送出去后,没有收到对端回复的ACK。
举个例子:发送端调用send()函数将一个int型数据(称之为A数据块)写入到socket中,A数据块会被马上发送到接收端,接着,发送端又调用send()函数写入一个int型数据(称之为B数据块),这时候,A块的ACK没有返回(已经存在了一个未被确认的小段),所以B块不会立即被发送,而是等A块的ACK返回之后(大概40ms)才发送。

ACK延迟机制

TCP协议中不仅仅有Nagle算法,还有一个ACK延迟机制:当接收端收到数据之后,并不会马上向发送端回复ACK,而是延迟40ms后再回复,它希望在40ms内接收端会向发送端回复应答数据,这样ACK就可以和应答数据一起发送,把ACK捎带过去。

Nagle的缺点与解决方案

如果TCP连接的一端启用了Nagle算法,另一端启用了ACK延时机制,而发送的数据包又比较小,则可能会出现这样的情况:发送端在等待上一个包的ACK,而接收端正好延迟了此ACK,那么这个正要被发送的包就会延迟40ms。
解决方案
开启TCP_NODELAY选项,这个选项的作用就是禁用Nagle算法。

#include <netinet/tcp.h>   // 注意,要包含这个头文件。
int opt = 1;   
setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY,&opt,sizeof(opt));

对时效要求很高的系统,例如联机游戏、证券交易,一般会禁用Nagle算法。

Tcp的分包与粘包

  • 分包:tcp报文的大小缺省是1460字节,如果发送缓冲区中的数据超出了1460字节,那么Tcp将会拆分多个包来发送,如果接收方及时从接收缓冲区中取走了数据,看起来就像是接收了多个报文。

  • 粘包:tcp接收到数据后,有序的放在缓冲区中,由于数据与数据之间不存在分隔符的说法,如果接收方没有及时的从缓冲区中取走数据,看起来就会和粘起来一样。

解决方案

为了解决上述出现的问题,我们对发送报文与接收报文的方式进行了修改。

  • 发送端:先发送报文长度,再发送报文内容。
  • 服务端:先接收报文长度,再接收报文内容。

结语

这一篇文章主要是为下一篇网络编程的服务端与客户端编写做一个引子,介绍一些有关网络编程的基本知识,因为下一篇文章将会给大家介绍在c++网络编程中有关服务端与客户端的编写,本文只做一些理论介绍,大家下篇见!

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

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

相关文章

黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录Day1

你好,我是Qiuner. 为记录自己编程学习过程和帮助别人少走弯路而写博客 这是我的 github gitee 如果本篇文章帮到了你 不妨点个赞吧~ 我会很高兴的 &#x1f604; (^ ~ ^) 想看更多 那就点个关注吧 我会尽力带来有趣的内容 2024黑马程序员 SpringCloud微服务开发与实战&#xff…

FPGA高端项目:FPGA帧差算法多目标图像识别+目标跟踪,提供11套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐FPGA帧差算法单个目标图像识别目标跟踪 3、详细设计方案设计原理框图运动目标检测原理OV5640摄像头配置与采集OV7725摄像头配置与采集RGB视频流转AXI4-StreamVDMA图像缓存多目标帧差算法图像识别目标跟踪模块视频输出Xilinx系列FPGA工程源…

【c++】cpp类的继承

目录 &#xff08;1&#xff09;继承概念与语法 &#xff08;2&#xff09;派生类的访问控制 &#xff08;3&#xff09;继承中的构造和析构 1.类型兼容性原则 2.继承中的构造析构调用原则 3.继承与组合混搭下构造和析构调用原则 &#xff08;4&#xff09;同名成员(函数…

slice

最重要的一张图 endlessSummer :summer[:5]//这是这张图真正厉害的地方为什么向函数传递slice允许在函数内部修改底层数组的元素&#xff1f; 因为slice值包含指向第一个sllice元素的指针&#xff0c;传入的slice允许在函数内部修改底层数组的元素。 复制的slice只是对底层的…

LabVIEW与Modbus协议的多点温度监控系统

LabVIEW与Modbus协议的多点温度监控系统 随着工业自动化和智能化水平的不断提升&#xff0c;对于现场监控技术的需求日益增长。开发了一种基于LabVIEW与Modbus协议的多点温度监控系统&#xff0c;实现高效、准确的温度数据采集、处理和显示&#xff0c;以及数据存储功能&#…

TCP/IP协议族中的TCP(一):解析其关键特性与机制

⭐小白苦学IT的博客主页⭐ ⭐初学者必看&#xff1a;Linux操作系统入门⭐ ⭐代码仓库&#xff1a;Linux代码仓库⭐ ❤关注我一起讨论和学习Linux系统 前言 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议&#xff09;是一种面向连接的、可靠的、基于字…

牛客社区帖子分页显示实现

下图是前端分页的组件&#xff1a; 下面是对应的静态html页面&#xff0c;每一个方块&#xff0c;都是一个a标签&#xff0c;可以点击&#xff0c;执行的链接是/community/index&#xff0c;GET请求&#xff0c;拼接的参数是current&#xff0c;也就是pageNum&#xff0c;只需…

力扣HOT100 208. 实现Trie(前缀树)

解题思路&#xff1a; class Trie {private Trie[] children; // 存储子节点的数组private boolean isEnd; // 记录是否为单词结尾public Trie() {children new Trie[26]; // 数组大小为26&#xff0c;代表26个小写字母isEnd false;}public void insert(String word) {Trie …

智能小程序 Ray 开发实践——基础内容组件 Text 和 Icon 介绍

Text 文本内容。 导入 import { Text } from ray-js/ray; Props 属性类型默认值说明支持平台classNamestring样式名涂鸦、微信selectablebooleanfalse文本是否可选涂鸦、微信onClick(e: { type: click }) > voidfalse点击事件涂鸦、微信 示例代码 基本使用 import Re…

【yolov8算法道路-墙面裂缝检测-汽车车身凹陷-抓痕-损伤检测】

yolo算法道路-墙面裂缝检测-汽车车身凹陷-抓痕-损伤检测 1. yolo算法裂缝检测-汽车车身凹陷-抓痕检测-汽车车身损伤检测2. yolo房屋墙面路面裂缝-发霉-油漆脱落-渗水-墙皮脱落检测3. 水泥墙面裂缝检测 YOLOv8算法是一种先进的目标检测技术&#xff0c;它基于YOLO系列算法的改进…

探索矿业数字化平台:实现智能化采矿与管理

随着信息技术的迅猛发展&#xff0c;矿业领域也在逐步实现数字化转型。数字化平台的出现为矿业企业带来了更高效、更智能的采矿与管理方式。本文将探讨矿业数字化平台的意义、特点以及未来发展方向。 ### 1. 数字化平台的意义 传统的矿业生产和管理方式存在诸多问题&#xff…

Python赋值运算符

目录 赋值运算符 将值赋给变量&#xff1a; 做加法运算之后完成赋值&#xff1a; 做减法运算之后完成赋值&#xff1a;- 做乘法运算之后完成赋值&#xff1a;* 做除法运算之后完成赋值&#xff1a;/ 做整除运算之后完成赋值&#xff1a;// 做幂次运算之后完成赋值&#xff1a;*…

Pytorch 计算深度模型的大小

计算模型大小的方法 卷积 时间复杂度 与 空间复杂度 的计算方式&#xff1a; C 通道的个数&#xff0c;K卷积核大小&#xff0c;M特征图大小&#xff0c;C_l-1是输入通道的个数&#xff0c;C_l是输出通道的个数 1 模型大小 MB 计算模型的大小的原理就是计算保存模型所需要…

在MySQL中isnull()函数不能作为替代null值!

在MySQL中isnull()函数不能作为替代null值&#xff01; 如下&#xff1a; 首先有个名字为business的表&#xff1a; SELECT ISNULL(business_name,no business_name) AS bus_isnull FROM business WHERE id2 直接运行就会报错&#xff1a; 错误代码&#xff1a; 1582 Incor…

cuDNN-Graph API

Graph API 为了适应越来越重要的算子融合需求&#xff0c;cuDNN8.0版本引入了Graph API&#xff0c;以提供更灵活的API接口。Graph API提供一个声明式的编程模型&#xff0c;此模型将计算操作描述为计算图。 用户首先需要构建操作图。从高层面来说&#xff0c;用户其实是在描…

Swift - Playground

文章目录 Swift - Playground1. 新建Playground2. View3. 图片4. ViewController5. Playground - 多Page6. 注释6.1 Playground的注释支持markup语法&#xff08;与markdown相似&#xff09;6.1.1 语法 Swift - Playground Playground可以快速预览代码效果&#xff0c;是学习语…

设计模式(九):组合模式

设计模式&#xff08;九&#xff09;&#xff1a;组合模式 1. 组合模式的介绍2. 组合模式的类图3. 组合模式的实现 1. 组合模式的介绍 组合模式&#xff08;Composite Pattern&#xff09;属于结构型模式&#xff0c;是用于把一组相似的对象当作一个单一的对象。 组合模式依据…

基于SpringBoot+Vue校园二手交易系统的设计与实现

系统介绍 自从新冠疫情爆发以来&#xff0c;各个线下实体越来越难做&#xff0c;线下购物的人也越来越少&#xff0c;随之带来的是一些不必要的浪费&#xff0c;尤其是即将毕业的大学生&#xff0c;各种用品不方便携带走导致被遗弃&#xff0c;造成大量的浪费。本系统目的就是让…

基于Spring Boot的旅游管理系统设计与实现

基于Spring Boot的旅游管理系统设计与实现 开发语言&#xff1a;Java框架&#xff1a;springbootJDK版本&#xff1a;JDK1.8数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/idea 系统部分展示 前台浏览管理界面图&#xff0c;通过内容列表可以获取网…

PotatoPie 4.0 实验教程(41) —— FPGA实现RISC-V 扩展 GPIO UART Timer功能

TD工程介绍 我们提供的TD工程里的RISC-V核默认就开启了GPIO UART扩展&#xff0c;可以看到还有SPI和I2C扩展。因此后面的实验中TD的工程我们基本不怎么修改TD的内容&#xff0c;只需要修改TD工具中Soc_Top.v文件中的TCM0_INITFILE为FD生成的固件名称即可&#xff0c;主要修我以…