粘包问题、mmap和分片上传

news2024/11/26 13:53:07

一、粘包问题:

如果一端要把文件发给另一端,要发送两个部分的数据:其一是文件名,用于对端创建文件;另一个部分是文件内容。服务端在接收文件名,实际上并不知道有多长, 所以它会试图把网络缓冲区的所有内容都读取出来,但是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 file1
    ARGS_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失败返回不是NULL
    for (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.coloradmin.cn/o/1941326.html

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

相关文章

怎么把照片变漫画?学会这几招让照片秒变漫画

在这个追求图片创意与趣味性的时代&#xff0c;照片的“变身”游戏正悄然风靡。 从滤镜的巧妙运用到拍摄姿势的创新突破&#xff0c;人们不断探索着让照片焕发新生的无限可能。 而今&#xff0c;一股将照片转化为漫画风格的新潮流正席卷而来&#xff0c;它不仅保留了照片的记…

【PPT方案】大数据湖建设方案

背 景&#xff1a;大数据湖的发展背景与建设理念 体 系&#xff1a;大数据湖体系规划与建设思路 生态圈&#xff1a;探索新兴业务入湖建设模式 共 享&#xff1a;大数据湖统一访问共享规划 运 营&#xff1a;大数据湖一体化运营管理建设 软件全套资料部分文档清单&…

恐怖数字暗影:猜中才能逃离

大家可以看看这个&#xff0c;也很有意思&#xff01; 猜数字游戏&#xff08;老六版&#xff09;-CSDN博客 1、 剧情介绍 在一个阴暗潮湿的古堡中&#xff0c;你独自一人走进了一间散发着诡异气息的房间。房间的正中央有一张古老的桌子&#xff0c;上面放着一本泛黄的羊皮卷…

Java二十三种设计模式-装饰器模式(7/23)

装饰器模式&#xff1a;动态扩展功能的灵活之选 引言 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型设计模式&#xff0c;用于在不修改对象自身的基础上&#xff0c;通过添加额外的职责来扩展对象的功能。 基础知识&#xff0c;java设计模式总体来说设计…

MT19937

MT19937 文章目录 MT19937题型1 逆向extract_number[SUCTF2019]MT 题型2 预测随机数[GKCTF 2021]Random 题型3逆向twist[V&N2020 公开赛]Backtrace 题型4 逆向init扩展题型WKCTF easy_random 现成模块randcrack库Extend MT19937 Predictor库 MT19937是一种周期很长的伪随机…

【C++】深刻基础笔记

目录 关于debug&#xff1a; 多文件编译&#xff1a; 编译器工作原理 预处理&#xff1a; 如何将机器二进制转换成可以看懂的文件 链接器的工作原理 Pointers指针 Reference引用 C线程 程序如何从源文件变成exe可执行文件&#xff1f; 首先是预处理器#include <..…

斐波那契数列的多种解法 C++实现,绘图部分用Python实现

斐波那契数列的多种解法 C实现&#xff0c;绘图部分用Python实现 flyfish 斐波那契数列&#xff08;Fibonacci sequence&#xff09;是一个经典的数列&#xff0c;定义如下&#xff1a; { 0 if n 0 1 if n 1 F ( n − 1 ) F ( n − 2 ) if n > 1 \begin{cases} 0 &…

c++网络编程实战——开发基于ftp协议的文件传输模块(二) 配置ftp服务与手动执行ftp命令

配置FTP服务 一.前言 博主的环境是阿里云服务器&#xff0c;操作系统版本为 ubuntu20.04,一下所有操作都基于以上环境下进行的操作&#xff0c;同时为了简化操作我将开放同一个云服务器的不同端口&#xff0c;让它同时充当服务端和客户端&#xff0c;大家如果想测试效果更好且…

Java基础:类与对象,递归,方法

类与对象的区别和联系 1.类是抽象的,概念的他是数据类型 2.对象是具体的实际的,代表一个具体事务 3.类是对象的模板,对象是类的个体 **对象在内存中的存在形式** 基本数据类型在堆,引用类型如String,数组在方法区 对象的属性 属性基本说明 1.成员变量or成员属性 属性的定…

双向链表<数据结构 C版>

目录 关于链表的分类 双向链表结构体 初始化 尾插 头插 打印 判断是否为空 尾删 头删 查找 指定位置之后的插入 指定位置的删除 销毁 关于链表的分类 根据链表的三大特性&#xff0c;单向or双向、带头or不带头、循环or不循环&#xff0c;可将链表分为2*2*2&#xf…

利用ascp下载SRA Explorer中转录组数据

最近在windows系统里下载了MobaXterm可以远程登入服务器&#xff0c;处理RNA的数据&#xff0c;需要从NCBI数据库上下载数据。本文提供用虚拟机ubuntu或者linux系统下载Aspera的方法和问题解决&#xff0c;以及从NCBI上批量下载数据库、最后得到一个项目里的所有fastq文件。 A…

前端:Vue学习-2

前端&#xff1a;Vue学习-2 1. vue的生命周期2. 工程化开发和脚手架Vue CLI2.1 组件化开发2.2 scoped解决样式冲突2.3 data是一个函数2.4 组件通信2.5 非父子通信- event bus事件&#xff0c;provide&inject 3.v-model原理->实现父子组件双向绑定4. sync 修饰符->实现…

谷粒商城实战笔记-42-前端基础-Vue-生命周期和钩子函数

下面是Vue官网关于生命周期及不同阶段的钩子函数的图示。 Vue 实例生命周期是指从一个组件被创建到最终被销毁的整个过程。 在这一过程中&#xff0c;Vue 提供了一系列的“钩子”函数&#xff0c;在生命周期的不同阶段执行自定义的代码。 以下是 Vue 对象生命周期的主要阶段…

C语言实现二叉树以及二叉树的详细介绍

目录 1.树概念及结构 1.1树的概念 1.2树的相关概念 1.3树的表示 2.二叉树概念及结构 2.1二叉树的概念 2.2特殊的二叉树 2.3二叉树的性质 2.4二叉树的存储结构 3.二叉树顺序结构--特殊的二叉树--堆及其实现 3.1堆的概念及结构 3.2堆的实现 3.2.1堆的结构 3.2.2堆…

filebeat生产环境配置

配置文件属性 生产配置 filebeat.inputs: - type: logenabled: truepaths: - /tmp/logs/*.log- /var/log/system.log- /var/log/wifi.logsymlinks: truejson.keys_under_root: truejson.message_key: xxxjson.add_error_key: true# 如果想卡部分日志&#xff0c;比如用时间作…

Monaco 使用 HoverProvider

Monaco 中自定义 Hover&#xff0c;Hover 效果是指当鼠标移动文字上展示出提示效果&#xff0c;就像页面上的 Tooltip 效果。最终页面的显示效果如下&#xff1a; 通过 registerHoverProvider 注册 Hover 触发时的处理方法 接口中提供了 4 个参数&#xff0c;前两个参数比较重…

python学习之闭包与装饰器

一、闭包 闭包允许一个函数访问并操作函数外部的变量&#xff08;即父级作用域中的变量&#xff09;&#xff0c;即使在该函数外部执行。 特性&#xff1a; (1)外部函数嵌套内部函数。 (2)外部函数可以返回内部函数。 (3)内部函数可以访问外部函数的局部变量。 def out()…

【jmeter边界值提取器】

【目的】 从响应头中取token的内容 【方案】 使用后置处理器-边界值提取器 【组件路径】HTTP请求->右键添加->后置处理器->边界提取器 用途&#xff1a;边界提取器(Boundary Extractor)是放在Sample请求之后执行的&#xff0c;用于获取左右边界中间的所有字符&#xf…

Windows配置Qt+VLC

文章目录 前言下载库文件提取文件编写qmakeqtvlc测试代码 总结 前言 在Windows平台上配置Qt和VLC是开发多媒体应用程序的一个重要步骤。Qt作为一个强大的跨平台应用开发框架&#xff0c;为开发人员提供了丰富的GUI工具和库&#xff0c;而VLC则是一个开源的多媒体播放器&#x…

基于STM32的农业大棚温湿度采集控制系统的设计

目录 1、设计要求 2、系统功能 3、演示视频和实物 4、系统设计框图 5、软件设计流程图 6、原理图 7、主程序 8、总结 &#x1f91e;大家好&#xff0c;这里是5132单片机毕设设计项目分享&#xff0c;今天给大家分享的是智能教室。 设备的详细功能见网盘中的文章《8、基…