Qt中QTcpSocket接收数据如何跨类传递实现业务逻辑处理
Qt Socket接收数据对外传递实现方法
Qt 异步场景下跨类传递Socket数据,最符合框架设计、耦合度最低的方案是通过自定义信号抛出数据,不需要暴露内部Socket对象,也不需要用全局变量中转,天然支持跨线程安全传递。
具体修改步骤
- 修改SocketTest头文件,新增数据传递信号
打开sockettest.h,在原本空的signals块里声明你需要的信号,既可以传原始字节流,也可以传解析完成的业务数值:signals: // 传递原始接收的字节数据,供上层自行解析 void rawDataRecv(const QByteArray &rawData); // 若在Socket层完成数据解析,可直接传递解析后的传感器数值 void sensorDataRecv(int recvValue); - 修改readyRead槽函数,接收数据时发射信号
打开sockettest.cpp,改写原本直接打印数据的readyRead函数,读完数据后通过emit关键字把数据抛出去:void SocketTest::readyRead() { QByteArray recvBytes = socket->readAll(); qDebug() << "收到数据:" << recvBytes; // 抛出原始字节数据 emit rawDataRecv(recvBytes); // 示例:将字节流转为整数,解析成功后抛出数值 bool parseFlag = false; int val = recvBytes.trimmed().toInt(&parseFlag); if (parseFlag) { emit sensorDataRecv(val); } }注意:TCP是面向流的协议,实际生产使用时会出现粘包、拆包问题,不要直接假设一次
readAll()拿到的就是一帧完整数据,需要根据你和服务端约定的协议(比如固定长度、特定分隔符、长度帧头)做分包处理,否则会出现解析错误。 - 上层业务类连接信号,实现控制逻辑
在你需要处理数据、控制对象移动的类中,持有SocketTest实例后,直接将信号和你的业务处理逻辑连接即可,不需要改动SocketTest的其他代码:
如果你需要自行处理原始数据解析,连接// 初始化Socket客户端 SocketTest *socketClient = new SocketTest(this); socketClient->Test(); // 连接传感器数据信号,写业务逻辑 connect(socketClient, &SocketTest::sensorDataRecv, this, [this](int received_data){ // 直接写你的控制逻辑 if( received_data == 5 ){ this->setX(this->x()+1); } });rawDataRecv信号即可拿到完整的原始字节流。
避坑说明
不要把内部的QTcpSocket *socket指针暴露给上层类直接调用read,也不要用全局变量缓存接收的数据:前者会让业务代码和Socket实现强耦合,后续换连接方式、改协议需要改动大量上层代码;后者会有线程安全、时序错乱的问题,多线程场景下极易出现崩溃、数据错乱。信号槽是Qt专门为异步事件设计的通信机制,自动处理跨线程的连接类型,是这类场景的标准实现方案。
内容的提问来源于stack exchange,提问作者O_DERE
相关产品推荐
相关产品推荐

