QT tcp通信,解决断包、粘包的问题

xian-yongchao 2018-08-17 原文

QT tcp通信,解决断包、粘包的问题

1、TCP和UDP的区别

  • TCP(transport control protocol,传输控制协议)是面向连接的,面向流的,提供高可靠性服务。收发两端(客户端和服务器端)都要有一一成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小且数据量小的数据,合并成一个大的数据块,然后进行封包。这样,接收端,就难于分辨出来了,必须提供科学的拆包机制。 即面向流的通信是无消息保护边界的(数据没有界限)
  • UDP(user datagram protocol,用户数据报协议)是无连接的,面向消息的,提供高效率服务。不会使用块的合并优化算法, 由于UDP支持的是一对多的模式,所以接收端的skbuff(套接字缓冲区)采用了链式结构来记录每一个到达的UDP包,在每个UDP包中就有了消息头(消息来源地址,端口等信息),这样,对于接收端来说,就容易进行区分处理了。 即面向消息的通信是有消息保护边界的。


这样就会造成如下三种情况:

1.接收端依次从发送端接收Msg1,Msg2;(正常)

2.Msg1被发送端分割为多段发送给接收端(或者接收端先接收到Msg1和Msg2的部分数据,再接收到msg2剩下的数据);(断/拆包)

3.Msg1和Msg2粘和在一起被发送端一次发送给接收端;(粘包)

PS:因此,通常我们需要将接收的消息通过整理,然后分别合成一个我们需要的数据包,然后才将这个消息发送给接收端。

2、解决TCP断包、粘包的的代码

1. 协议如下

报头

长度

数据段(N个字节)

校验和

0x55AA

len

命令类型(id)

目标地址

主机地址

预留

其它

CRC

2 个字节

2 个字节(从报头到检验和所有长度)

n1个字节

n2个字节

n3个字节

n3个字节

n4个字节

1个字节(从报头到数据完的校验和)。

 2.代码如下:

void TcpClient::rcvSlot()
{
  static QByteArray allBa;  //用来存所有文件
  allBa.append(tcpClient->readAll());  //读取数据
  int head = allBa.indexOf(HEAD);    //报文头的位置,HEAD=0x55aa
  uint16_t length = 0;                               //报文(协议中)的长度
  QByteArray currentBa;
  int id = 0;
  while (-1 != head)           //报文头检验
  {
    allBa = allBa.mid(head);      //去掉报头之前的
    memcpy(&length, allBa.data() + 2, 2);
    if (allBa.size() >= length)      //长度够,进行解析。报文长度校验
    {
      currentBa = allBa.mid(0, length); //获取当前完整包
      id = Mymethod:isCRC(currentBa);  //报文的和校验和id校验。(这里的id不小于0,Mymethod:isCRC返回命令id,校验通过返回大于0,异常返回-1)
      if (-1 != id)
      {
        emit getPacketSignal(id, currentBa);
        allBa = allBa.mid(length);
        qDebug() << “接收指令:” << currentBa.toHex().toUpper();
      }
    }
    head = allBa.indexOf(HEAD);   //刷新报文头的位置
  }
}

 

发表于 2018-08-17 11:32 ttxs027 阅读() 评论() 编辑 收藏

 

版权声明:本文为xian-yongchao原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/xian-yongchao/p/9488847.html

QT tcp通信,解决断包、粘包的问题的更多相关文章

  1. 使用msys2在window下构建和使用Linux的软件

    目录 前言 安装 使用 总结 前言 在window下构建Linux编译环境是很常见的,以前用过mingw弄过差 […]...

  2. 常量变量及作用域

    变量 变量为程序中最基本的存储单元,其要素包含变量名,类型及作用域 type varName = value...

  3. 汇编学习笔记之转移指令

    什么是转移指令: 可以修改IP,或同时修改CS和IP的指令统称为转移指令。转移指令可以通过修改CS和IP的值来 […]...

  4. SpringBoot Web 学习

    SpringBoot Web 开发 静态资源 打开WebMvcAutoConfiguration类里面的静态类 […]...

  5. qt creator源码全方面分析(3-1)

    目录 qtcreator.pro 包含qtcreator.pri include(filename) Qt版本 […]...

  6. Qt Installer Framework翻译(7-3)

    控制脚本 对于每个安装程序,您可以指定一个控制脚本,用来与安装程序的部分UI或功能进行交互。控制脚本可以在向导 […]...

  7. QT串口助手(四):数据发送

    作者:zzssdd2 E-mail:zzssdd2@foxmail.com 一、前言 开发环境:Qt5.12. […]...

  8. QT/C++插件式框架、利用智能指针管理内存空间的实现、动态加载动态库文件

    QT、C++插件式框架、主要原理还是 动态库的动态加载、 dlopen()函数、下面为动态加载拿到Plugin […]...

随机推荐

  1. Java新手编程中心-在线学习 – 王君

    Java编程语言是一种坚实而多能的语言,它使开发人员能够: 在一种平台上编写软件,而在另一种平台上运行。 创建 […]...

  2. java项目打包部署

    网上打包的教程很多, 但是自己动手总归出现各种各样的问题,自己总结下: 由于刚刚接触JAVA,做了一个简单的j […]...

  3. SQL SELECT INTO 语句用法及案例分析

    SQL SELECT INTO 语句 通过 SQL,您可以从一个表复制信息到另一个表。 SELECT INTO […]...

  4. 机器学习(七) PCA与梯度上升法 (上)

    一、什么是PCA 主成分分析 Principal Component Analysis 一个非监督学的学习算法 […]...

  5. bzoj1193: [HNOI2006]马步距离

    1193: [HNOI2006]马步距离 Time Limit: 10 Sec  Memory Limit:  […]...

  6. MongoDB 4.0 角色(roles)详解

    引言:一般情况下,mongoDB 数据库都要建立认证连接,这就需要用户对数据库创建管理员和用户认证,而对于mo […]...

  7. 专家教你用镜像第一期:主机宝镜像使用详解!云服务器代金券等你拿~!!

    专家教你用镜像第一期:主机宝镜像使用详解 (分分钟帮你搞定云服务器环境部署)   优势强大的主机宝镜像(Lin […]...

  8. python 冷知识(装13 指南)

    python 冷知识(装13 指南) list1 += list2 和 list1 = list1 + lis […]...

展开目录

目录导航