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;
      		}
}

五、经验总结

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

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

  • 7
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值