当前位置: 首页 > article >正文

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.kler.cn/a/447348.html

相关文章:

  • SQL进阶技巧:如何计算商品需求与到货队列表进出计划?
  • 【自动化】Python SeleniumUtil 工具 开启开发者模式 自动安装油猴用户脚本等
  • C#中方法参数传值和传引用的情况
  • 使用vcpkg安装opencv>=4.9后#include<opencv2/opencv.hpp>#include<opencv2/core.hpp>无效
  • 相机内外参知识
  • 源码编译llama.cpp for android
  • python 曲线拟合,曲线拟合交点
  • Linux搭建Alist(本地存储)
  • AS-REP Roasting离线爆破攻击
  • 探索AI安全治理,打造大模型时代的可信AI
  • 雅思真题短语梳理(五)
  • Facebook的隐私保护政策:用户数据如何在平台上被管理?
  • WSL切换默认发行版
  • 启动打印服务提示:Http端口已被使用,请修改
  • 全脐点曲面当且仅当平面或者球面的一部分
  • android recycleview 中倒计时数据错乱
  • puppet 配置 6 变量的特殊用法
  • python--在服务器上面创建conda环境
  • 多线程设计模式-保护性暂停之面向对象
  • django中cookie与session的使用
  • 【背景信息】Proxmox Virtual Environment 创建AD域实现统一身份认证(一)
  • Android 搭建AIDL Client和Server端,双向通信
  • OpenCV实现实时人脸检测和识别
  • Python 图像处理领域的十一个基础操作
  • 聚观早报 | 百度回应进军短剧;iPad Air将升级OLED
  • 7-2 排序