最全处理粘包问题及源码

  1. qt下解决粘包问题:数据前四个字节放入数据长度

        const QByteArray &data
    
        QByteArray aps;
        int len=data.length();
        aps[3] = (unsigned char)(0x000000ff & len); 
        aps[2] = (unsigned char)((0x0000ff00 & len) >> 8);
        aps[1] = (unsigned char)((0x00ff0000 & len) >> 16);
        aps[0] = (unsigned char)((0xff000000 & len) >> 24);
        aps+=data;
    	aps前四个字节代表了要发送数据的长度
    
  2. 将数据base64编码后用@#符号夹在中间,接收端解码

3.最近跳到了一个使用标准库的公司,需要使用标准库string和char * 处理粘包问题,具体编码解码:
编码:

		string xystr = ~(~)//获取需要传输的数据
        int dataLength =xystr.size();
        //将数据前四个字节放入数据长度以解决粘包
        int realLength = dataLength + sizeof(int);
        char *sendData = new char[realLength];
        memset(sendData, 0, realLength*sizeof(char));
        unsigned int num1, num2, num3, num4;
        char *p = (char *)&dataLength;
        num1 = ((int)*p);
        num2 = ((int)*(p+1));
        num3 = ((int)*(p+2));
        num4 = ((int)*(p+3));
        memcpy(sendData, &num4, sizeof(int));
        memcpy(sendData+sizeof(char), &num3, sizeof(int));
        memcpy(sendData+2*sizeof(char), &num2, sizeof(int));
        memcpy(sendData+3*sizeof(char), &num1, sizeof(int));
        memcpy(sendData+sizeof(int), xystr.c_str(), xystr.size());

解码:

if(read(sock,recvbuf,sizeof(recvbuf))>0)
                    {
                            int len=0;
                            char *cint=(char *)&len;
                            (*cint)=(int)recvbuf[3];
                            (*(cint+1))=recvbuf[2];
                            (*(cint+2))=recvbuf[1];
                            (*(cint+3))=recvbuf[0];
                            for(int i=0;i<4;i++){printf("%d\n",recvbuf[i]);}
                            printf("数据长度:%d\n",len);
                            j=1;
                    }

当服务端向客户端用tcp不断的发送数据时,如果客户端突然断开,继续调用发送数据那么可能会发送 broken pipe 信号导致服务关闭,可以通过信号处理解决,但是也可以根据突然断开的时候发送数据返回int型-1,此时判断一下如果返回-1则终止发送就可以解决此问题
4.新写的功能是将一个数据在改变的时候使用socket发送,所以用了while循环,程序老是崩溃,崩溃语句随机,很头疼,领导指导了一下,当数据没有变化时死循环,会导致cpu占用率飙升,导致系统级关闭程序信号产生,在循环里加入了sleep后,就没有崩溃了。(需要注意的是,一定要自己new的自己delete!!!!!!)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
.版本 2 .支持库 spec .支持库 sock .程序集 窗口程序集_启动窗口 .子程序 _按钮2_被单击 客户1.发送数据 (取重复字节集 (10000, 到字节集 (“1”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (20000, 到字节集 (“2”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (30000, 到字节集 (“3”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (40000, 到字节集 (“4”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (50000, 到字节集 (“5”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (60000, 到字节集 (“6”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (70000, 到字节集 (“7”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (80000, 到字节集 (“8”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (90000, 到字节集 (“9”)) + 到字节集 (“分隔符”)) 客户1.发送数据 (取重复字节集 (100000, 到字节集 (“0”)) + 到字节集 (“结尾符”)) .子程序 _服务器1_数据到达 .局部变量 取回数据, 字节集 .局部变量 数据数组, 文本型, , "0" .局部变量 次数, 整数型 .局部变量 临时数据, 字节集, 静态 .局部变量 得到的封, 文本型 取回数据 = 服务器1.取回数据 () .判断开始 (取字节集右边 (取回数据, 6) ≠ 到字节集 (“结尾符”))  ' 6为结尾符的长度;这里检测封是否部发送完毕,如果没有发送完毕就会把发送来的封数据进行累加     临时数据 = 临时数据 + 取回数据 .默认     临时数据 = 临时数据 + 取回数据  ' 检测到结尾符出现,说明数据已经发送完毕,这里把最后发送来的带有结尾符的数据加上就OK了。     临时数据 = 子字节集替换 (临时数据, 到字节集 (“结尾符”), , 取字节集长度 (临时数据) - 6, 6)  ' 6为结尾符的长度;这里把结尾符替换尾空,剩余数据尾完整的纯净数据。     数据数组 = 分割文本 (到文本 (临时数据), “分隔符”, )  ' 这里把收到的数据进行分割处理,无论服务器发送了多少次,都统一按分隔符分割     调试输出 (“封数量:” + 到文本 (取数组成员数 (数据数组)))     .计次循环首 (取数组成员数 (数据数组), 次数)         得到的封 = 数据数组 [次数]  ' 这里得到分割后的封文本。         调试输出 (“第” + 到文本 (次数) + “个封的大小:” + 到文本 (取文本长度 (得到的封)))  ' 这里的大小和上面发送封的大小相同,可以看到封的分割次数。     .计次循环尾 ()     临时数据 = {  } .判断结束 .子程序 __启动窗口_创建完毕 客户1.连接 (取本机名 (), 8888)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值