Socket 收发内部拆包封包函数

在socket通信的时候,有时候数据比较大,内部缓存会溢出,导致发送或接收数据不正确。

针对这个情况,封装了一个接收和发送的底层函数,根据缓存大小批次发送和接收,内部有自己的缓冲区,测试情况良好。

//发送函数

const int SEND_BUFFER_LEN =1024;//发送缓冲区大小

int Send_package_Data(const SOCKET  mysocket, const uint32_t ui32Length, const char * pvalue)

{

    uint32_t irecv=0;

    int ipos=0;

    if (ui32Length<= SEND_BUFFER_LEN)//小于1024发一包数据

    {      

        char  Buffer_one[SEND_BUFFER_LEN+1]={0};发送缓冲区

        memset(Buffer_one,0,sizeof(Buffer_one));

        memcpy(Buffer_one,pvalue,ui32Length);

        irecv=0;

        uint32_t pos1 = 0;//下一次发送需要开始的位置                        

        while(pos1 < ui32Length)

        {

            irecv = send(mysocket, Buffer_one+pos1, ui32Length-pos1, 0);

            if(irecv <=0) //错误

            {

                printf("Send failed: %s\r\n", strerror(errno));

                break;

            }  

            pos1 += irecv;

        }      

       

        return irecv;

    }

    else//大于1024发多包数据

    {              

        const uint32 ics=ui32Length / SEND_BUFFER_LEN;

        const uint32 imod=ui32Length % SEND_BUFFER_LEN;

        printf("ics = %d\r\n",ics);

        printf("imod = %d\r\n",imod);      

       

        for (uint32 i = 0; i < ics; i++)

        {

            ipos=SEND_BUFFER_LEN*i;

           

            char  Buffer_cs[SEND_BUFFER_LEN+1]={0};发送缓冲区

            memset(Buffer_cs,0,sizeof(Buffer_cs));

            memcpy(Buffer_cs,pvalue+ipos,SEND_BUFFER_LEN);

            irecv=0;

            uint32_t pos2 = 0;//下一次发送需要开始的位置                        

            while(pos2 < SEND_BUFFER_LEN)

            {

                irecv = send(mysocket, Buffer_cs+pos2, SEND_BUFFER_LEN-pos2, 0);

                if(irecv <=0) //错误

                {

                    printf("Send failed: %s\r\n", strerror(errno));

                    break;

                }  

                pos2 += irecv;

            }                      

        }  

        if (irecv <= 0)

        {

            return irecv;

        }  

        if (imod>0)

        {          

            ipos=SEND_BUFFER_LEN*ics;

            char  Buffer_mod[SEND_BUFFER_LEN+1]={0};发送缓冲区

            memset(Buffer_mod,0,sizeof(Buffer_mod));

            memcpy(Buffer_mod,pvalue+ipos,imod);

            printf("Buffer_mod: %s\r\n", Buffer_mod);          

            irecv=0;

            uint32_t pos3 = 0;//下一次发送需要开始的位置                        

            while(pos3 < imod)

            {

                irecv = send(mysocket, Buffer_mod+pos3, imod-pos3, 0);

                if(irecv <=0) //错误

                {

                    printf("Send failed: %s\r\n", strerror(errno));

                    break;

                }  

                pos3 += irecv;

            }

        }

        return irecv;

    }

    return 0;  

}

//接收函数

const int RECV_BUFFER_LEN =1024;//发送缓冲区大小

int  Recv_package_Data(const SOCKET  mysocket, uint32_t  ui32Length, char * pvalueData)

{

    if (ui32Length<=0) return -200;

    //清空缓冲区

    memset(pvalueData,0,ui32Length);    

    uint32_t irecv=0;

    int ipos=0;

    if (ui32Length<= RECV_BUFFER_LEN)//小于1024收一包数据

    {      

        char  Buffer_one[RECV_BUFFER_LEN+1]={0};接收缓冲区      

        uint32_t pos1 = 0;//下一次发送需要开始的位置

        irecv=0;

        while(pos1 < ui32Length)

        {

            irecv = recv(mysocket, Buffer_one+pos1, ui32Length-pos1, 0);

            if(irecv <=0) //错误

            {

                printf("Recv_klv_value::Buffer_one::recv failed: %s\r\n", strerror(errno));

                break;

            }  

            pos1 += irecv;

        }

        if (irecv>0)

        {

            memcpy(pvalueData,Buffer_one,ui32Length);

        }

        return irecv;

    }

    else//大于1024多包接收数据

    {              

        const uint32 ics=ui32Length / RECV_BUFFER_LEN;

        const uint32 imod=ui32Length % RECV_BUFFER_LEN;

        printf("ics = %d\r\n",ics);

        printf("imod = %d\r\n",imod);      

       

        for (uint32 i = 0; i < ics; i++)

        {

            ipos=RECV_BUFFER_LEN*i;

           

            char  Buffer_cs[RECV_BUFFER_LEN+1]={0};接收缓冲区

           

            irecv=0;

            uint32_t pos2 = 0;//下一次发送需要开始的位置

            while(pos2 < RECV_BUFFER_LEN)

            {

                irecv = recv(mysocket, Buffer_cs+pos2, RECV_BUFFER_LEN-pos2, 0);

                if(irecv <=0) //错误

                {

                    printf("Recv_klv_value::Buffer_one::recv failed: %s\r\n", strerror(errno));

                    break;

                }  

                pos2 += irecv;

            }

            if (irecv>0)

            {

                memcpy(pvalueData+ipos,Buffer_cs,RECV_BUFFER_LEN);

            }          

        }  

        if (irecv <= 0)

        {

            return irecv;

        }  

        if (imod>0)

        {          

            ipos=RECV_BUFFER_LEN*ics;

            char  Buffer_mod[RECV_BUFFER_LEN+1]={0};接收缓冲区

            uint32_t pos3 = 0;//下一次发送需要开始的位置

            irecv=0;

            while(pos3 < imod)

            {

                irecv = recv(mysocket, Buffer_mod+pos3, imod-pos3, 0);

                if(irecv <=0) //错误

                {

                    printf("Recv_klv_value::Buffer_mod::recv failed: %s\r\n", strerror(errno));

                    break;

                }  

                pos3 += irecv;

            }              

           

            if (irecv > 0)

            {

                memcpy(pvalueData+ipos,Buffer_mod,imod);

            }

        }

        return irecv;

    }

    return 0;  

    recv函数的返回值解析如下:

    如果成功接收数据,则返回接收到的字节数。

    如果连接已关闭,则返回0。

    如果发生错误,则返回-1,并可以通过errno变量获取具体的错误信息。

}

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

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

相关文章

RK3588 , mpp硬编码yuv, 保存MP4视频文件.

RK3588 , mpp硬编码yuv, 保存MP4视频文件. ⚡️ 传送 ➡️ Ubuntu x64 架构, 交叉编译aarch64 FFmpeg mppRK3588, FFmpeg 拉流 RTSP, mpp 硬解码转RGBRk3588 FFmpeg 拉流 RTSP, 硬解码转RGBRK3588 , mpp硬编码yuv, 保存MP4视频文件.

powershell美化

powershell美化 写在前面 除了安装命令&#xff0c;其他都是测试命令&#xff0c;后续再写进配置文件 安装主题控件 安装主题oh-my-posh&#xff0c;powershell中执行 winget install JanDeDobbeleer.OhMyPosh -s winget oh-my-posh init pwsh | Invoke-Expression # 查看…

2024/12/22周报

文章目录 摘要Abstract深度学习文献阅读1. 背景与问题2. 发明目的3. 方法与实现3.1 数据采集与变量选取3.2 BP神经网络建立稳态预测模型3.3 构建多目标优化函数3.4 多目标差分进化算法求解优化3.5 最优决策变量筛选3.6 实时控制 4. 系统实现5. 实际效果与验证5.1 仿真验证5.2 神…

前端编程训练 异步编程篇 请求接口 vue与react中的异步

文章目录 前言代码执行顺序的几个关键点接口请求vue与react中的异步 vue中的异步react的state修改异步 前言 本文是B站三十的前端课的笔记前端编程训练,异步编程篇 代码执行顺序的几个关键点 我们可以理解为代码就是一行一行&#xff0c;一句一句是执行&#xff08;定义变…

Excel生成DBC脚本源文件

Excel制作 新建一个Excel&#xff0c;后缀为“.xls” 工作本名称改为“CAN_Matrix” 在首行按照列来起名字&#xff0c;在里面只需要填写必须的内容即可。 列数名称第0列Message Name第1列Message Format第2列Message ID第3列Message Length (byte)第4列Message Transmitte…

16.2、网络安全风险评估技术与攻击

目录 网络安全风险评估技术方法与工具 网络安全风险评估技术方法与工具 资产信息收集&#xff0c;可以通过调查表的形式把我们各类的资产信息进行一个统计和收集&#xff0c;掌握被评估对象的重要资产分布&#xff0c;进而分析这些资产关联的业务面临的安全威胁以及存在的安全…

C++-----函数与库

数学中的函数与编程中的函数对比 数学中的函数 - 数学函数是一种映射关系&#xff0c;例如&#xff0c;函数\(y f(x)x^{2}\)&#xff0c;对于每一个输入值\(x\)&#xff0c;都有唯一确定的输出值\(y\)。它侧重于描述变量之间的数量关系&#xff0c;通常通过公式来表示这种关系…

Loki 微服务模式组件介绍

目录 一、简介 二、架构图 三、组件介绍 Distributor&#xff08;分发器&#xff09; Ingester&#xff08;存储器&#xff09; Querier&#xff08;查询器&#xff09; Query Frontend&#xff08;查询前端&#xff09; Index Gateway&#xff08;索引网关&#xff09…

C++ OpenGL学习笔记(1、Hello World空窗口程序)

终于抽出时间系统学习OpenGL 教程&#xff0c;同时也一步一步记录怎样利用openGL进行加速计算。 目录 1、环境准备1.1、库的下载1.2、库的选择及安装 2、OpenGL第一个项目&#xff0c;Hello World!2.1、新建hello world控制台项目2.2、配置openGL环境2.2.1 包含目录配置2.2.2 …

Linux系统命令基础

Linux命令⾏ [pypylinux ~]$ 普通⽤户py&#xff0c;登陆后 [rootpylinux ~]# 超级⽤户root&#xff0c;登录后root代表当前登录的⽤户 分隔符pylinux 主机名~ 当前的登录的位置&#xff0c;此时是家⽬录# 超级⽤户身份提示符 $ 普通⽤户身份提示符操作系统⽬录分隔符 Linux目录…

不同版本的 Redis 的键值对内存占用情况示例

不同版本的 Redis 的键值对内存占用情况示例 文章目录 不同版本的 Redis 的键值对内存占用情况示例Redis 6.0redisObjectdictEntrysds&#x1f340; 数据结构&#x1f340; sdslen() 函数&#x1f340; sdsReqType() 函数&#x1f340; sdsHdrSize() 函数 内存分配 - malloc() …

实现 WebSocket 接入文心一言

目录 什么是 WebSocket&#xff1f; 为什么需要 WebSocket&#xff1f; HTTP 的局限性 WebSocket 的优势 总结&#xff1a;HTTP 和 WebSocket 的区别 WebSocket 的劣势 WebSocket 常见应用场景 WebSocket 握手过程 WebSocket 事件处理和生命周期 WebSocket 心跳机制 …

2024.7 XAI 遇见 LLM:可解释 AI 与大型语言模型之间关系的调查

https://arxiv.org/pdf/2407.15248 问题 Q1&#xff1a;XAI 技术当前如何与 LLMs 集成&#xff1f;Q2&#xff1a;将 LLMs 与 XAI 方法融合的新兴趋势是什么&#xff1f;Q3&#xff1a;当前相关文献存在哪些差距&#xff0c;哪些领域需要进一步研究&#xff1f; 挑战 LLMs …

前端滚动锚点(点击后页面滚动到指定位置)

三个常用方案&#xff1a; 1.scrollintoView 把调用该方法的元素滚动到屏幕的指定位置&#xff0c;中间&#xff0c;底部&#xff0c;或者顶部 优点&#xff1a;方便&#xff0c;只需要获取元素然后调用 缺点&#xff1a;不好精确控制&#xff0c;只能让元素指定滚动到中间&…

前端笔记——大数据量浏览器卡顿优化思路

多任务数据量处理卡顿问题 任务分批次 为避免阻塞&#xff0c;可以将 长时间的单一任务 拆分成多个小任务并分批执行。这样可以在两次任务之间让浏览器有时间处理渲染、用户输入等操作。两种常见方法&#xff1a; setTimeout 方法&#xff1a; 使用 setTimeout 将任务分段&a…

数智化转型是什么?

数智化转型是指企业通过数字化&#xff08;Digitalization&#xff09;和智能化&#xff08;Intelligentization&#xff09;技术的结合&#xff0c;推动业务流程、产品服务、组织管理的全面升级&#xff0c;从而提升效率、增强创新能力&#xff0c;并实现更高价值。相比传统的…

RIP实验

要求及分析 路由器上分别配置环回 连接路由器的线路网段为12.1.1.0/24、23.1.1.1.0/24 R1和R3连接的网络地址分别为192.168.1.0/24/192.168.2.0/24 整个网络使用RIP达到全网可达 配置 先配置路由器各接口ip和环回和pc ip网关掩码&#xff08;图略&#xff09; 进行 RI…

Oracle 中间件 Webcenter Portal服务器环境搭建

环境信息 服务器基本信息 如下表&#xff0c;本次安装总共使用2台服务器&#xff0c;具体信息如下&#xff1a; Webcenter1服务器 归类 SOA服务器 Ip Address 172.xx.xx.xx.xx HostName wcc01.xxxxxx.com Alias wccprd01 Webcenter2服务器 归类 OSB服务器 Ip Addr…

macOS 配置 vscode 命令行启动

打开 vscode 使用 cmd shift p 组合快捷键&#xff0c;输入 install 点击 Install ‘code’ command in PATH Ref https://code.visualstudio.com/docs/setup/mac

3、交换机IP路由功能

每个用例前自己最好先画个图&#xff0c;不然容易绕晕&#xff0c;这篇文章写好久了&#xff0c;自己都觉得有点绕 一、直连路由 如果一个交换机与另一个交换机时直连着的并且他们用来连接的端口属于同网段&#xff0c;那么这种情况下他们就属于直连路由。不需要做任何配置便可…