TCP 组包和拆包算法-转载

网络 -- TCP概述、三次握手、四次挥手、粘包分包、数据分段 数据重传 要明白的一点:网络传输本身就是不可靠的;可能丢包或者数据重复. 案例: 客户端发送了3个数据包, 经过传输到达服务器端,但是只收到了3和1的包; 数据包2丢包了 发送和接收的次序出现问题, 客户端先发的数据包1,但服务器先收到的是数据包3; 网络中的路由节点较多,难免发生节点故障;数据包发送到网络中,使用了不同的网络链路,前后次序可能不一致. (1)首先网络丢包难以避免,那么要保证不丢包就可用重发机制,服务器每次收到 阅读详情
/*************************************
文件名: server.c
TCP 组包和拆包实现算法
 
 
作者:   马中海
QQ:     284358503
Email: zhonghaima001@163.com
*/
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <sys/socket.h>
#include <linux/in.h>
#include <string.h>
 
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
 
 
#define BUF_SIZE 1024*5
 
 
//#define TCP_PACK_DEBUG 1
 
 
int main()
{
 
    int nBufuseLen=0;       //缓冲区里用到的长度
    int nRevOnceLen=0;      //read 一次读到的长度
    int nPackLen=0;         //每一包的长度,包括头和两个长度和尾字节
    int bufSize=BUF_SIZE;
 
 
    unsigned char buf[BUF_SIZE];     //read 的缓存
 
 
    int i=0;
 
 
    int sfp,nfp; /* 定义两个描述符 */
    struct sockaddr_in s_add,c_add;
    int sin_size;
    unsigned short portnum=6000; /* 服务端使用端口 */
    printf("Hello,welcome to my server !\r\n");
    sfp = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == sfp)
    {
        printf("socket fail ! \r\n");
        return -1;
    }
    printf("socket ok !\r\n");
    /* 填充服务器端口地址信息,以便下面使用此地址和端口监听 */
    bzero(&s_add,sizeof(struct sockaddr_in));
    s_add.sin_family=AF_INET;
    s_add.sin_addr.s_addr=htonl(INADDR_ANY); /* 这里地址使用全0,即所有 */
    s_add.sin_port=htons(portnum);
    /* 使用bind进行绑定端口 */
    if(-1 == bind(sfp,(struct sockaddr *)(&s_add), sizeof(struct sockaddr)))
    {
        printf("bind fail !\r\n");
        return -1;
    }
    printf("bind ok !\r\n");
    /* 开始监听相应的端口 */
    if(-1 == listen(sfp,5))
    {
        printf("listen fail !\r\n");
        return -1;
    }
    printf("listen ok\r\n");
    //  while(1)
    {
 
 
        //    char buf[1027];
        //    int readlen;
 
 
        sin_size = sizeof(struct sockaddr_in);
        /* accept服务端使用函数,调用时即进入阻塞状态,等待用户进行连接,在没有客户端进行连接时,程序停止在此处,
           不会看到后面的打印,当有客户端进行连接时,程序马上执行一次,然后再次循环到此处继续等待。
           此处accept的第二个参数用于获取客户端的端口和地址信息。
            */
        nfp = accept(sfp, (struct sockaddr *)(&c_add), &sin_size);
        if(-1 == nfp)
        {
            printf("accept fail !\r\n");
            return -1;
        }
        printf("accept ok!\r\nServer start get connect from %#x : %#x\r\n",ntohl(c_add.sin_addr.s_addr),ntohs(c_add.sin_port));
        /* 这里使用write向客户端发送信息,也可以尝试使用其他函数实现 */
        if(-1 == write(nfp,"hello,welcome to my server \r\n",32))
        {
            printf("write fail!\r\n");
            return -1;
        }
 
 
//头0xF9   两个长度字节   数据   尾0xF8
        while(1)
        {
#ifdef TCP_PACK_DEBUG
            {
                printf("bufSize = %d ,nBufuseLen = %d\n",bufSize,nBufuseLen);
            }
#endif
            if(bufSize>nBufuseLen)
            {
                nRevOnceLen=read(nfp,buf+nBufuseLen,bufSize-nBufuseLen);
                nBufuseLen=nBufuseLen+nRevOnceLen;
 
 
#ifdef TCP_PACK_DEBUG
                {
                    printf("nBufuseLen = %d>3\n",nBufuseLen);
                }
#endif
                /*
                                printf(" nRevOnceLen data:\n");
                                for(i=0; i<nRevOnceLen; i++)
                                {
                                    printf(" 0x%x ",buf[i]&0xFF);
                                }
                                printf(" \n");
                */
 
 
            }
            else
            {
                printf("buf if full\n");
            }
 
 
 
 
            while(nBufuseLen>3)            //用到的大于3个字节
            {
 
 
                /*            printf(" nBufuseLen data:\n");
                            for(i=0; i<nBufuseLen; i++)
                            {
                                printf(" 0x%x ",buf[i]&0xFF);
                            }
                            printf(" \n");
                */
 
#ifdef TCP_PACK_DEBUG
                {
                    printf("buf[0] = 0x%x \n",buf[0]&0xFF);
                }
#endif
                if((buf[0]&0xFF)==0xF9)         //头
                {
                    nPackLen=(buf[1]*256)+buf[2];
 
 
#ifdef TCP_PACK_DEBUG
                    {
                        printf("nBufuseLen=%d ,nPackLen=%d\n",nBufuseLen,nPackLen);
                    }
#endif
 
 
                    if(nBufuseLen>=nPackLen)                //大于和=
                    {
#ifdef TCP_PACK_DEBUG
                        {
                            printf("buf[nPackLen-1] = 0x%x \n",buf[nPackLen-1]&0xFF);
                        }
#endif
 
 
                        if((buf[nPackLen-1]&0xFF)==0xF8)                  //尾
                        {
                            //找到一包数据,所有的数据都往前移动nPackLen个字节
#ifdef TCP_PACK_DEBUG
                            {
                                printf("head 0x%x length %d tail 0x%x \n", buf[0]&0xFF,nPackLen,buf[nPackLen-1]&0xFF);
                            }
#endif
 
 
                            for(i=0; i<nBufuseLen-nPackLen; i++)
                            {
                                buf[i]=buf[nPackLen+i];
                            }
 
 
                            nBufuseLen=nBufuseLen-nPackLen;      //用到的字节变小了
                            //   continue;           //不要read了
                        }
                        else
                        {
 
 
#ifdef TCP_PACK_DEBUG
                            printf("buf[%d-1]=0x%x,(buf[0]!=0xF8)\n",nPackLen,(buf[nPackLen-1]!=0xF8));        //这里应该不会执行
                            for(i=0; i<5; i++)
                            {
                                printf(" 0x%x ",buf[i]&0xFF);
                            }
                            printf(" \n");
#endif
                            printf(" (buf[nPackLen-1]&0xFF)!=0xF8 \n");
                            nBufuseLen=0;           //清除错误的包   //这里应该不会执行
 
 
 
 
                            break;
 
 
                        }
                    }
                    else
                    {
 
 
#ifdef TCP_PACK_DEBUG
                        printf(" nBufuseLen<=nPackLen\n");
#endif
                        break;
                    }
                }
                else
                {
                    printf(" (buf[0]!=0xF9)\n");        //这里应该不会执行
                    nBufuseLen=0;           //清除错误的包   //这里应该不会执行
                    break;
                }
            }
 
 
            /*
                        if((0xFF&buf[0])!=0xF2)
                        {
                            printf("readlen = %d buf  0x%x  0x%x  0x%x \n",readlen,0xFF&buf[0],0xFF&buf[1],0xFF&buf[2]);
                        }
 
 
 
 
                        if(readlen!=1027)
                            printf("readlen = %d buf  0x%x  0x%x  0x%x \n",readlen,0xFF&buf[0],0xFF&buf[1],0xFF&buf[2]);
 
 
            */
        }
        //  close(nfp);
    }
    // close(sfp);
    return 0;
}

C++网络通信之TCP数据包发送与接收 1.数据包设计 a.登陆命令 //命令枚举 enum SOCK_CMD { SC_LOGIN,//登陆 SC_LOGOUT,//注销 SC_LOGIN_RET,//登陆结果 SC_LOGOUT_RET,//注销结果 SC_ERR //错误命令 }; b.数据包格式结构 //网络数据头 struct SOCK_DATA_HEAD { short LEN;//数据长度 short SOCK_CMD;//数据对应命令 }; c.登陆结构体 //登陆结构体 struct LOGIN 阅读详情

相关推荐

SAP SD 顾问面试问题 consultant interview questionnaire

以下是我个人目前面试团队 SD顾问问题的小结,希望对大家有所帮助, 也可能有回答错误的地方,希望同行不吝赐教。 也希望各位顾问们讲你们遇到的一些面试问题做个跟贴,方便大家共同进步,谢谢。   面试问题清单:  一、销售订单类型影响: 可用性检查,交货类型,输出,信贷,定价,需求,报表,合作伙伴,文本,不完整日志,交货开票,订单开票,公司间开票,统计组,屏幕顺序组,参数文件...

weixin_33825683的博客 1809

Socket 中级篇(四) TCP组包、粘包、拆包的原理

第一章、简介 1、这篇博客我想阐述什么? 在利用Socket+Tcp通信中,如果不采用开源库(比如SuperSocket)来实现,那么就是自己写了。既然自己写的东西,必须考虑稳定性、有效性、可行性等等。 直到今天,在用Socket/TCP做视频监控过程中,当网络较慢时,Socket/tcp通信,并不能一次性地把发送缓存区的数据发送出去。如果接受端不做处理,而是按接...

xpj8888的博客 8816

Marin说PCB之LPDDR5的布线注意事项--03

这个规则中是把每个字节中的WCK to RDQS 以及DM / DQ to WCK等长规则都加到了DM / DQ这个等长规则中去了,因为芯片手册上的设计要求中的DM / DQ这个group的等长误差是+-50MIL, WCK to RDQS的等长group的规则是62.5MIL,DM / DQ to WCK等长group的规则是相对松一些是150MIL。其实上面的等长规则还是建少了一些的,例如手册上要求的每个channel的WCK0:1,WCK2:3等长误差在+-488MIL,这个规则建议还是补上去吧。

weixin_45223454的博客 1229

详解一次完整的数据包传输过程 -- 层层递进

文章目录 例子 PC1 发送http请求到ServerStep1: PC1封装数据包Step 2: 数据到达集线器Step3: 数据到达R1Step4: 数据到达R2Step5: 交换机处理Step6: 服务器处理反向传输总结 题记:本文主要是摘自CCNA指南中讲的,再加上自己的理解,详细阐述一次完整的数据传输过程。之前在考CCIE的时候也看过,后来有些忘记,特总结记录。 读此文章之前,先弄懂下面5个基本知识点: 封装报文是从上层到下层(应用层 --> 传输层 --> ..

wearlee的博客 3646

初级文章【西门子】字符拼接成字符串

针对S7-400极其以下PLC,1200往上据说有专门的块了呢,首先,我是不用库的,需要什么函数会自己写,OK进入正题。 首先,我们有一个DB块,里面有14个char,一个14位的char数组和一个14位的string。如下图。 我们的目的是将char1-char10拼接成一个string。 第一种方式:第一步,将char放进数组。 ​​​​​​​ 相信大家都能看明白,但是我还是要解释解释 L取值2 T赋值到临时变量DBNO(INT) OPN DB [#DBNO]获取DB块,这一句.

NS_Speak(IVAV) 1万+

010、Zephyr RTOS开发环境搭建(Docker)

摘要 本文分享了使用Docker搭建Zephyr RTOS开发环境的实践经验。作者通过团队新人配置环境的真实案例,指出传统安装方式存在版本冲突、缓存污染等问题,而Docker方案能确保环境一致性。文章详细介绍了自定义Docker镜像的设计思路,重点解决工具链版本匹配、Python虚拟环境隔离等问题,将镜像体积从2GB优化到800MB。提供了从拉取镜像到点亮LED的完整工作流程,并总结了USB设备直通、文件权限、缓存问题等常见陷阱。还探讨了多阶段构建、CI集成等进阶用法,同时客观分析了Docker方案的局限性

m0_50546716的博客 78

代码笔记 | TCP 组包和拆包算法

/************************************* 文件名: server.c TCP 组包和拆包实现算法 */ #include #include #include #include #include #include #include #include #include #define BUF_SIZE 1024*

代码屠夫CodePudge 1827

[VT虚拟化驱动]正式启动VT

文章目录前言一、vmlaunch正式开始虚拟化二、使用步骤1.引入库2.读入数据总结 前言 本章开始真正实现一个最简单的VT框架,当然,只是能跑起来一个VT驱动了,没有并包括EPT,EPT后面再讲 提示:以下是本篇文章正文内容,下面案例可供参考 一、vmlaunch正式开始虚拟化 执行VMLAUNCH指令执行后,就正式进入虚拟化了,再该指令执行之前,得先保存Guest当前的环境,执行完VMLAUNCH后,要恢复Guest的环境,让Guest就像什么都没发生一样,所以需要保存和恢复Guest的各种寄存器的值

吾无法无天的博客 3661

SOCKET的封包与拆包

SOCKET的封包与拆包 转载汤姆瑞德尔最后发布于2017-04-10 17:15:15阅读数 573收藏 展开 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就是封包和拆包.自从我从事网络通讯编程工作以来(大概有三年的时间了),我一直在思索和改进封包和拆包的方法.下面就针对这个问题谈谈我的想法,抛砖引玉.若有不对,不妥之处,恳求大家指正.在此先谢过大家了. 一.为什么...

cxu123321的博客 815

基于深度学习的堰塞坝表层颗粒物质识别研究

本文提出一种基于深度学习的堰塞坝表层颗粒物质智能识别方法,针对颗粒分布散乱、背景复杂的问题,采用"大颗粒逐个识别、密集小颗粒分块识别"策略。结合Mask R-CNN、SLIC和AlexNet构建识别模型,通过无人机影像实现自动识别。实验表明该方法精度超过90%,具备迁移能力。文章提供了Python实现代码,涵盖数据预处理、SLIC分割、模型构建(Mask R-CNN和AlexNet)及训练流程,为堰塞坝应急抢险提供技术支持。

huanghm88的专栏 181

【WorkBuddy专栏58】腾讯为什么要「自己打自己」——7款AI智能体产品全景对比与「赛马」逻辑深度拆解

【WorkBuddy专栏57】你的左侧空间不是「日任务清单」——工作空间才是 WB 变聪明的核心秘密

AI人人懂 673

tcp 发送数据长度比预设缓存大_阿里Java一面:熟悉TCP粘包、拆包?说说粘包、拆包产生原因...

大家好,我是小寒!今天给小伙伴介绍一下TCP粘包、拆包!有自己看法的也可以在评论区留言探讨,也可以转发关注下我以后会长期分享!此文是转载于博客园一位博主的写作链接:https://www.cnblogs.com/qdhxhz/p/10277239.html一、TCP粘包、拆包图解假设客户端分别发送了两个数据包D1和D2给服务端,由于服务端一次读取到字节数是不确定的,故可能存在以下四种情况:服务端分...

weixin_39671621的博客 142

Jetson agx Orin 适配Xenomai4

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。

xiaoning132的专栏 465

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

粘包、拆包

粘包、拆包发生原因 (1)socket缓冲区与滑动窗口 先明确一个概念:每个TCP socket在内核中都有一个发送缓冲区(SO_SNDBUF)和一个接收缓冲区(SO_RCVBUF),TCP的全双工的工作模式以及TCP的滑动窗口便是依赖于这两个独立的buffer以及此buffer的填充状态。SO_SNDBUF和SO_RCVBUF 在windows操作系统中默认情况下都是8K ...

weixin_30666401的博客 144

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

网络通信--封包和拆包

转载自:http://blog.youkuaiyun.com/fengge8ylf/article/details/793808 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就是封包和拆包.自从我从事网络通讯编程工作以来(大概有三年的时间了),我一直在思索和改进封包和拆包的方法.下面就针对这个问题谈谈我的想法,抛砖引玉.若有不对,不妥之处,恳求大家指正.在此先谢过大家了.

每一次对问题的深究,总会收获新的知识和体会 1363

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

tcp黏包与拆包

目录 1.黏包2.封包与拆包 1.黏包 ​ 1.为什么出现黏包 1.发送方原因 tcp默认会使用Nagle算法,而Nagle算法主要做两件事。1)只有上一个分组得到确认,才会发送下一个分组 2)收集多个小分组,在一个确认到来时一起发送。2.接收方原因 tcp接收到分组时,并不会立刻送至应用层处理,或者说应用层并不一定会立即处理;实际上,tcp将收到的分组保存至接收缓存...

weixin_30855761的博客 188

TCP粘包拆包问题

原文:https://my.oschina.net/andylucc/blog/625315 摘要: 粘包拆包问题是处于网络比较底层的问题,在数据链路层、网络层以及传输层都有可能发生。我们日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生这个问题,因此这篇文章只讨论发生在传输层的TCP粘包拆包问题。 粘包拆包问题是处于网络比较底层的问题,在数据链路层、网络层以及传输...

weixin_30858241的博客 99

TCP拆包粘包问题

对于刚接触TCP网络编程的人有时候碰到一些问题,比如当客服端发送一串消息到服务端,服务端只收到消息的一半,或者当连续发送两个消息到服务端,服务端同时收到这两个消息但无法解析。这就是今天要讲的TCP拆包粘包现象。 拆包粘包产生的原因 我们可以通过以下图进行说明 1.图一是正常的情况下包的发送和...

cherry93925的博客 205

[转载]封包和拆包

原文:http://blog.youkuaiyun.com/fengge8ylf/archive/2006/06/13/793808.aspx 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就是封包和拆包.自从我从事网络通讯编程工作以来(大概有三年的时间了),我一直在思索和改进封包和拆包的方法.下面就针对这个问题谈谈我的想法,抛砖引玉.若有不对,不妥之处,恳求大家指正.在此先谢过大家了.一.为什么...

weixin_30755393的博客 104

IPsec传输模式下ESP报文的装包和拆包过程

原创文章,拒绝转载 装包过程 总体流程图 过程描述 在原IP报文中找到TCP报文部分,在其后添加相应的ESP trailer信息。 ESP trailer 包含三部分:Padding,Pad length 和 Next header。Padding 即使用块加密时,最后一个数据块长度不足时所做的填充。Pad length 指填充的长度,方便拆包时找到用来填充的数据段。Next header...

weixin_30387339的博客 216

TCP传输协议中如何解决丢包问题

TCP在不可靠的网络上实现可靠的传输,必然会有丢包。TCP是一个“流”协议,一个详细的包将会被TCP拆分为好几个包上传,也是将会把小的封裝成大的上传,这就是说TCP粘包和拆包难题。 ...

cuiniaotu8405的博客 502

tcp粘包分析

tcp粘包分析

weixin_43841155的博客 139

封包和拆包

转载:作者:fengge8ylf 博客:http://blog.youkuaiyun.com/fengge8ylf 对于基于TCP开发的通讯程序,有个很重要的问题需要解决,就是封包和拆包.自从我从事网络通讯编程工作以来(大概有三年的时间了),我一直在思索和改进封包和拆包的方法.下面就针对这个问题谈谈我的想法,抛砖引玉.若有不对,不妥之处,恳求大家指正.在此先谢过大家了. 一.为什么基于TCP的通讯程序...

weixin_53370274的博客 58

转载:TCP通信粘包问题分析和解决(完整版)

在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的。因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小、数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 对于UDP,不会使用块的合并...

qq_20999867的博客 666

IOS开发Scoket接受报文不全(分多次接受)的TCP粘包问题

转载自:http://blog.youkuaiyun.com/zhangxinrun/article/details/6721495 这两天看csdn有一些关于socket粘包,socket缓冲区设置的问题,发现自己不是很清楚,所以查资料了解记录一下:  一 .两个简单概念长连接与短连接: 1.长连接     Client方与Server方先建立通讯连接,连接建立后不断开, 然

fang8380的专栏 3713
上一篇: C++日志类
下一篇: c++实现对windwos 下socket 的封装(实现封包及拆包处理)--
Syee001
博客等级 码龄14年 3粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值