• QTcpSocket中数据接受不全和数据不实时等问题


    一、背景

    在光纤项目中,作为查看信号实时波形、配置采集卡等功能的本地客户端,实现该客户端过程中,出现数据接受不全,运行时间久了会出现信号延迟等问题,达不到波形实时的效果。

    二、实现方式

    1、 本地客户端是通过服务器不断的获取数据,然后协议封装之后等到数据。

    2、 客户端这边通过Qt中的类QTcpSocket来接受服务端的数据。即信号和槽:

    connect(m_pSocket, SIGNAL(readyRead()), this, SLOT(receiveData()));

    想法是采集卡每获取一组数据中间会有几十毫秒的间隔,这边的信号也就有实时触发并接收数据。

    三、原因分析

    客户端接受函数用的是Qt类中封装的readAll()函数,当初的想法是服务端有多少数据发送过来,客户端就全部读取。出现数据接受不全的问题会不会是服务端发送的数据太大,函数readAll()一下子接受不过来,readAll()官方文档介绍如下:

    官方文档介绍说一下子接受所有数据,又查看了源码

    循环读取接受,想的是会不会这个MaxByteArraySize较小

    很明显不是reaAll的问题。

    换个思路,因为不改变采集卡参数的情况下,每组数据大小是固定的,于是就将接收函数换成read(qint64
    maxSize)读取,这就造成了运行时间长了,波形不实时的问题,也造成了我感觉是画图造作时间大于每组发送数据时间的假象。

    重回起点,问题根源应该不在接收函数这里,那就应该是信号不及时触发,于是写了个测试代码,服务端循环发送,每次发很小的数据,客户端信号触发次数不对等,也就是服务端发了三次,客户端这边可能一次触发将三次数据全部接受。

    之前的误解就是发送端wirte一次,readyread就会触发一次,上面的测试例子就是几组数据readyread触发一次,write一次大数据量的数据,readyread会触发多次,简单来说就是符合粘包分包机制。

    接着往下深究,对于tcp,数据是连在一起的分不开的,最小粒度是1字节。发送端的应用程序write函数一次写了多少数据,接收方的系统是不知道的。那么接收方系统到底接收到多少数据才发送给qt应用程序呢?这个算法是这样的:超时和超过缓冲。超时:无论来了多少数据,超过这个时间,系统就会发送当前接收到的数据给qt应用程序。超过缓冲,在未超时的情况下,系统缓冲区满了,系统就会将数据发送给qt应用程序。系统TCP/IP缓冲最大是65536个字节。

    四、解决方案:

    知道了信号触发的机制,在槽函数中用哪种读取数据函数就不纠结了,这里还是采用的是readAll(),一下全部读掉。代码如下:

    int OneFrameDataLen = 1000;           //没帧数据大小
    Buffer += m_pSocket->readAll();      //一次接受全部数据
    ReceiveLen = Buffer.size();                 //接受的数据大小
    if(ReceiveLen < OneFrameDataLen)          //分包处理,数据不够接续接收
    {
           return;	
    }
    //接受的数据大于等与一包的数据大小,粘包处理
    while(1)
    {
    		ReceiveBuf = Buffer.mid(0, OneFrameDataLen);      //截取获取一完整包的数据
      		Buffer=Buffer.mid(OneFrameDataLen, ReceiveLen - OneFrameDataLen);   //获取多余
           		Do something;      //处理数据函数
          		ReceiveLen = Buffer.size();   //剩下数据大小
           		if(ReceiveLen< OneFrameDataLen)   //不满一包数据退出,等待下次信号触发
    		{
          			 break;
          		}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    五、经验总结

    本文介绍了QtTcpSocket数据接受不全,数据不实时的问题,分享了在实际项目的解决问题的方案和遇到问题的分析,为后具有相同问题的解决提供一定的参考。

    在此问题中,作者分析问题时走了一定的弯路,第一时间没有抓住问题的根源所在,通过本文,作者分享在开发过程中的一些思考和解决方案,并不代表最佳方案和实践,仅供参考。

  • 相关阅读:
    计算机网络——分层结构
    python使用pytest接口自动化测试的使用
    (压缩PDF)Adobe Acrobat DC
    jvm堆大小的设置
    SpringFramework:Spring IOC
    nlp自然语言处理
    获得京东商品详情 API
    有没有什么赚钱的副业?分享,适合学生赚钱的30个副业!
    Gorm之gorm.io/gorm源码
    LeetCode--324. 摆动排序 II(C++描述)
  • 原文地址:https://blog.csdn.net/weixin_43719811/article/details/126481348