粘包问题、mmap和分片上传

一、粘包问题:

如果一端要把文件发给另一端,要发送两个部分的数据:其一是文件名,用于对端创建文件;另一个部分是文件内容。服务端在接收文件名,实际上并不知道有多长, 所以它会试图把网络缓冲区的所有内容都读取出来,但是send底层基于的协议是TCP协议 ——这是一种流式协议。这样的情况下,服务端没办法区分到底是哪些部分是文件名而哪些 部分是文件内容。完全可能会出现服务端把文件名和文件内容混杂在一起的情况,这种就是 江湖中所谓的"粘包"问题。

定义一个结构体规定TCP发送和接收的实际长度从而确定单个消息的边界。 

typedef struct train_s{
int size;
char buf[1000];
} train_t;

1、文件比较大时使用循环机制:发送方使用一个循环来读取文件内容,每 当读取一定字节的数据之后,将这些数据的大小和内容填充进小火车当中;接收方就不断的 使用recv接收小火车的火车头和车厢,先读取4个字节的火车头,再根据车厢长度接收后续 内容。

2、 服务端往客户端已经关闭的网络socket中写入数据,导致进程收到SIGPIPE信号异常终止。解决方法是给send的最后一个参数加上MSG_NOSIGNAL选项。

3、调用recv的时 候,需要传入一个整型的长度参数,但是遗憾的是,这个长度参数是描述的是最大的长度, 而实际recv的长度可能并没有达到最大的长度——因为TCP是一种流式协议,它只能负责每 个报文可靠有序地发送和接收,但是并不能保证传输到网络缓冲区当中的就是完整的一个小 火车(即数据到达有延迟)。解决方案就是给recv函数设置MSG_WAITALL属性,这样的话, recv在不遇到EOF或者异常关闭的情况就能一定把最大长度数据读取出来。

二、mmap:

采用read和send传输数据时,首先打开一个普通文件,数据会从磁盘通过DMA设备传输到内存,即文件对象当中的内核缓冲区部分,然后调用read 数据会从内核缓冲区拷贝到一个用户态的buf 上面(buf是 read 函数的参数),接下来调用send,就将数据拷贝到了网络发送缓冲区,最终实现了文件传输。

但这里涉及到了大量不必要的拷贝操作。

 使用mmap系统调用直接建立文件和用户态空间buf的映射。可以减少一次拷贝。

下面是使用mmap的例子:

//假设文件本身的内容是hello#include <func.h>
int main(int argc, char *argv[])
{// ./mmap file1ARGS_CHECK(argc, 2);// 先open文件int fd = open(argv[1], O_RDWR);ERROR_CHECK(fd, -1, "open");// 建立内存和磁盘之间的映射char *p = (char *)mmap(NULL, 5, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);ERROR_CHECK(p, MAP_FAILED, "mmap"); // mmap失败返回不是NULLfor (int i = 0; i < 5; ++i){printf("%c", *(p + i));}printf("\n");*(p + 4) = '0';for (int i = 0; i < 10; ++i){printf("%c", *(p + i));}munmap(p, 5);close(fd);return 0;
}

 运行结果:

mmap的底层原理 :

read/write 是让数据在内核态的文件对象和用户态内存之间进行来回拷 贝,文件对象会和一片由操作系统管理的内存区域(被称为页缓存)相关联,一般来说,操作系统会选 择一个合适策略并使用专门的硬件(比如DMA设备)来同步磁盘和页缓存当中的内容,这样 read/write 操 作最终就会影响到磁盘。而 mmap 的处理就更加简单粗暴,它直接把页缓存的一部分映射到用户态内存, 这样用户在用户态当中的操作就直接对应页缓存的操作。 这样看上去的话, mmap 的效率总是会比 read/write 更加高,因为它避免了一次数据在用户态和内核态 之间的拷贝。但是考虑到 read/write 的特殊性质——它们总是顺序地而不是随机地访问磁盘文件的内 容,所以操作系统可以根据这个特点进行优化,比如文件内容的预读等等,最终经过测试—— read/write 在顺序读写的时候性能更好,而 mmap 在随机访问的时候性能更好。

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

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

相关文章

Anaconda下安装配置Jupyter

Anaconda下安装配置Jupyter 1、安装 conda activate my_env #激活虚拟环境 pip install jupyter #安装 jupyter notebook --generate-config #生成配置文件提示配置文件的位置&#xff1a; Writing default config to: /root/.jupyter/jupyter_notebook_config.py检查版本&am…

android studio中svn的使用

第一步&#xff0c;建立一个项目。 第二步&#xff0c;share project。 第三步&#xff0c;选择存放的位置&#xff0c;然后添加提交信息&#xff0c;最后点击share。这样就可以在svn上面看到一个空的项目名称。 第四步&#xff0c;看到文件变成了绿色&#xff0c;点击commit图…

来聊聊redis集群数据迁移

写在文章开头 本文将是笔者对于redis源码分析的一个阶段的最后一篇&#xff0c;将从源码分析的角度让读者深入了解redis节点迁移的工作流程&#xff0c;希望对你有帮助。 Hi&#xff0c;我是 sharkChili &#xff0c;是个不断在硬核技术上作死的 java coder &#xff0c;是 CS…

华为OD机考题(HJ61 放苹果)

前言 经过前期的数据结构和算法学习&#xff0c;开始以OD机考题作为练习题&#xff0c;继续加强下熟练程度。 描述 把m个同样的苹果放在n个同样的盘子里&#xff0c;允许有的盘子空着不放&#xff0c;问共有多少种不同的分法&#xff1f; 注意&#xff1a;如果有7个苹果和3…

C语言 | Leetcode C语言题解之第275题H指数II

题目&#xff1a; 题解&#xff1a; int hIndex(int* citations, int citationsSize) {int left 0, right citationsSize - 1;while (left < right) {int mid left (right - left) / 2;if (citations[mid] > citationsSize - mid) {right mid - 1;} else {left mi…

Java 中的线程

创建线程的三种方式 方式一&#xff1a;继承Thread类 实现步骤&#xff1a; 继承Thread类并重写run()方法&#xff1b; 创建线程并启动。 代码实现&#xff1a; public class MyThread extends Thread {Overridepublic void run() {for(int i0; i<100; i) {System.out…

DB-GPT:LLM应用的集大成者

整体架构 架构解读 可以看到&#xff0c;DB-GPT把架构抽象为7层&#xff0c;自下而上分别为&#xff1a; 运行环境&#xff1a;支持本地/云端&单机/分布式等部署方式。顺便一提&#xff0c;RAY是蚂蚁深度参与的一个开源项目&#xff0c;所以对RAY功能的支持应该非常完善。…

Vue自定义指令与Vue插槽学习

文章目录 自定义指令1.指令介绍2.自定义指令3.自定义指令语法4.指令中的配置项 自定义指令-指令的值1.使用效果2.语法 插槽-默认插槽1.作用2.用处4.插槽的基本语法 插槽-具名插槽1.作用2.具名插槽语法3.v-slot的简写 插槽总结1.插槽分类2.作用3.场景4.使用步骤 自定义指令 1.指…

实现Nginx的反向代理和负载均衡

一、反向代理和负载均衡简介 1.1、反向代理 反向代理(reverse proxy)指:以代理服务器来接受Internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给Internet上请求连接的客户端。此时代理服务器对外就表现为一个反向代理服务器。 反向代…

【Android Compose】ListView效果

【Android Compose】ListView效果 1、Column、Row 和 Box2、LazyColumn和LazyRow3、Compose 中的状态4、ListView效果5、android-compose-codelabs Jetpack Compose 使用入门 Jetpack Compose 教程 Jetpack Compose 1、Column、Row 和 Box Compose 中的三个基本标准布局元素是 …

算法day05 master公式估算递归时间复杂度 归并排序 小和问题 堆排序

2.认识O(NlogN)的排序_哔哩哔哩_bilibili master公式 有这样一个数组&#xff1a;【0&#xff0c;4&#xff0c;2&#xff0c;3&#xff0c;3&#xff0c;1&#xff0c;2】&#xff1b;假设实现了这样一个sort()排序方法&#xff0c; 将数组二分成左右两等分&#xff0c;使用so…

linux、windows、macos,命令终端清屏

文章目录 LinuxWindowsmacOS 在Linux、Windows和macOS的命令终端中&#xff0c;清屏的命令或方法各不相同。以下是针对这三种系统的清屏方法&#xff1a; Linux clear命令&#xff1a;这是最常用的清空终端屏幕的命令之一。在终端中输入clear命令后&#xff0c;屏幕上的所有内容…

【计算机网络】TCP/IP——流量控制与拥塞控制

学习日期&#xff1a;2024.7.22 内容摘要&#xff1a;TCP的流量控制与拥塞控制 流量控制 一般来说&#xff0c;我们总是希望数据传输的快一些&#xff0c;但是如果数据传输的太快&#xff0c;接收方可能就来不及接收&#xff0c;这就会导致数据的丢失&#xff0c;流量控制正是…

Vue中渲染函数

why? 在绝大多数情况下&#xff0c;Vue 推荐使用模板语法来创建应用。然而在某些使用场景下&#xff0c;我们真的需要用到 JavaScript 完全的编程能力。这时渲染函数就派上用场了。 例如&#xff1a;下方要在多个模型上方设置对话框&#xff0c;如果使用Vue模板语法相对较困难…

小技巧:如何在已知PDF密码情况下去掉PDF的密码保护

第一步&#xff0c;用Edge打开你的pdf&#xff0c;输入密码进去 第二步&#xff0c;点击打印 第三步&#xff0c;选择导出PDF&#xff0c;选择彩印 第四步&#xff0c;选择导出位置&#xff0c;导出成功后打开发现没有密码限制了&#xff01;

什么是长效住宅IP?

长效住宅IP的定义 长效住宅IP&#xff0c;简而言之&#xff0c;是指长期稳定、非动态更换的住宅网络IP地址。这类IP地址通常由互联网服务提供商&#xff08;ISP&#xff09;分配给居民家庭用户&#xff0c;用于上网、网络通信等日常网络活动。与传统的动态IP相比&#xff0c;长…

数据结构day5

一、思维导图 二、课后练习 1、使用循环链表完成约瑟夫环问题 2、使用栈&#xff0c;完成进制转换&#xff08;输入&#xff1a;一个整数&#xff0c;进制数&#xff0c;输出&#xff1a;该数的对应的进制数&#xff09; //头文件 #ifndef DEC_TO_BIN_H #define DEC_TO_BIN_H…

【WAF剖析】10种XSS某狗waf绕过姿势,以及思路分析

原文&#xff1a;【WAF 剖析】10 种 XSS 绕过姿势&#xff0c;以及思路分析 xss基础教程参考&#xff1a;https://mp.weixin.qq.com/s/RJcOZuscU07BEPgK89LSrQ sql注入waf绕过文章参考&#xff1a; https://mp.weixin.qq.com/s/Dhtc-8I2lBp95cqSwr0YQw 复现 网站安全狗最新…

Electron 渲染进程直接调用主进程的API库@electron/remote引用讲解

背景 remote是个老库&#xff0c;早期Electron版本中有个remote对象&#xff0c;这个对象可以横跨所有进程&#xff0c;随意通信&#xff0c;后来官方认为不安全&#xff0c;被干掉了&#xff0c;之后有人利用Electron的IPC通信&#xff0c;底层通过Promise的await能力&#x…

Air780EP- AT开发-阿里云应用指南

简介 使用AT方式连接阿里云分为一机一密和一型一密两种方式&#xff0c;其中一机一密又包括HTTP认证二次连接和MQTT直连两种方式 关联文档和使用工具&#xff1a; AT固件获取在线加/解密工具阿里云平台 准备工作 Air780EP_全IO开发板一套&#xff0c;包括天线SIM卡&#xff0…