当前位置: 首页 > ai >正文

【QT】类A接收TCP数据并通过信号通知类B解析

以下是基于Qt的完整示例代码,包含类A接收TCP数据并通过信号通知类B解析的实现:

------------------ ClassA.h 网络数据接收类 ------------------
#pragma once#include <QTcpServer>
#include <QTcpSocket>
#include <QObject>class ClassA : public QObject
{Q_OBJECT
public:explicit ClassA(QObject *parent = nullptr);void startServer(quint16 port);  // 启动TCP服务器signals:void dataReceived(const QByteArray &data);  // 数据接收信号private slots:void onNewConnection();void onReadyRead();void onDisconnected();private:QTcpServer *m_server;QTcpSocket *m_socket;QByteArray m_buffer;  // 用于处理粘包/分包
};
------------------ ClassA.cpp ------------------
#include "ClassA.h"
#include <QDebug>ClassA::ClassA(QObject *parent) : QObject(parent)
{m_server = new QTcpServer(this);connect(m_server, &QTcpServer::newConnection, this, &ClassA::onNewConnection);
}void ClassA::startServer(quint16 port)
{if (!m_server->listen(QHostAddress::Any, port)) {qWarning() << "Server start failed:" << m_server->errorString();} else {qInfo() << "Server listening on port" << port;}
}void ClassA::onNewConnection()
{m_socket = m_server->nextPendingConnection();connect(m_socket, &QTcpSocket::readyRead, this, &ClassA::onReadyRead);connect(m_socket, &QTcpSocket::disconnected, this, &ClassA::onDisconnected);qInfo() << "New client connected";
}void ClassA::onReadyRead()
{m_buffer += m_socket->readAll();// 示例拆包逻辑:假设协议头4字节表示数据长度(网络字节序)while (m_buffer.size() >= 4) {// 读取数据长度(假设大端序)quint32 packetLength = qFromBigEndian<quint32>(reinterpret_cast<const uchar*>(m_buffer.constData()));// 检查数据是否完整if (m_buffer.size() < static_cast<int>(packetLength + 4)) {break;  // 数据不完整,等待下次接收}// 提取完整数据包QByteArray packet = m_buffer.mid(4, packetLength);emit dataReceived(packet);  // 发射信号// 移除已处理数据m_buffer.remove(0, 4 + packetLength);}
}void ClassA::onDisconnected()
{qInfo() << "Client disconnected";m_socket->deleteLater();
}
------------------ ClassB.h 数据解析类 ------------------
#pragma once#include <QObject>class ClassB : public QObject
{Q_OBJECT
public:explicit ClassB(QObject *parent = nullptr);public slots:void parseData(const QByteArray &data);  // 数据解析槽函数
};
------------------ ClassB.cpp ------------------
#include "ClassB.h"
#include <QDebug>ClassB::ClassB(QObject *parent) : QObject(parent) {}void ClassB::parseData(const QByteArray &data)
{// 示例解析逻辑qDebug() << "\n=== Received Packet ===";qDebug() << "Length:" << data.length();qDebug() << "Hex Content:" << data.toHex();qDebug() << "Text Content:" << data;qDebug() << "=======================";
}
------------------ main.cpp 测试程序 ------------------
#include <QCoreApplication>
#include "ClassA.h"
#include "ClassB.h"int main(int argc, char *argv[])
{QCoreApplication a(argc, argv);// 创建对象ClassA receiver;ClassB parser;// 连接信号槽QObject::connect(&receiver, &ClassA::dataReceived, &parser, &ClassB::parseData);// 启动服务器receiver.startServer(12345);// 模拟客户端发送数据(实际应用中应为独立客户端)QTcpSocket client;client.connectToHost(QHostAddress::LocalHost, 12345);if(client.waitForConnected()) {// 构造测试数据包(4字节长度头 + 实际数据)QByteArray packet1 = "Hello";QByteArray packet2 = "Qt Signal/Slot!";// 添加长度头(大端序)QByteArray data;QDataStream stream(&data, QIODevice::WriteOnly);stream.setByteOrder(QDataStream::BigEndian);// 数据包1stream << static_cast<quint32>(packet1.size());data.append(packet1);// 数据包2stream << static_cast<quint32>(packet2.size());data.append(packet2);client.write(data);client.waitForBytesWritten();}return a.exec();
}

代码说明

  1. ClassA

    • 实现TCP服务器功能(端口监听、客户端连接管理)
    • 使用m_buffer处理TCP粘包/分包问题
    • 当收到完整数据包时发射dataReceived信号
  2. ClassB

    • 通过槽函数parseData接收数据
    • 示例解析逻辑展示数据基本信息(长度、十六进制和文本内容)
  3. main.cpp

    • 创建ClassA和ClassB实例
    • 连接信号与槽
    • 模拟客户端发送包含两个数据包的测试数据

运行效果

Server listening on port 12345
New client connected=== Received Packet ===
Length: 5
Hex Content: "48656c6c6f"
Text Content: "Hello"
========================== Received Packet ===
Length: 14
Hex Content: "5174205369676e616c2f536c6f7421"
Text Content: "Qt Signal/Slot!"
=======================

关键点解释

  1. 粘包处理

    • 使用m_buffer累积数据
    • 通过4字节长度头判断数据完整性
    • 使用mid()remove()处理缓冲区
  2. 字节序处理

    • 使用qFromBigEndian读取网络字节序
    • 通过QDataStream设置字节序
  3. 线程安全

    • 如果ClassA/ClassB在多个线程工作,需添加:
      connect(&receiver, &ClassA::dataReceived, &parser, &ClassB::parseData, Qt::QueuedConnection);
      
  4. 扩展建议

    • 在ClassB中添加具体业务协议解析逻辑
    • 在ClassA中添加错误处理(errorOccurred信号)
    • 使用QSharedPointer管理类实例生命周期
http://www.xdnf.cn/news/7492.html

相关文章:

  • mac .zshrc:1: command not found: 0 解决方案
  • 从头实现react native expo本地生成APK
  • 无线通信基础
  • 适合初学者的机器学习路线图
  • 【Linux】第二十四章 管理网络安全
  • windows/linux 模拟鼠标键盘输入
  • Python subprocess简单理解
  • layui 介绍
  • 如何保存解析后的商品信息?
  • Python合法图片爬虫开发全指南
  • 优化dp贪心数论
  • 深入解析Node.js文件系统(fs模块):从基础到进阶实践
  • React TS中如何化简DOM事件的定义
  • 【Linux】初见,基础指令
  • SMT贴片元器件识别要点与工艺解析
  • 经典面试题:TCP 三次握手、四次挥手详解
  • 基于ssm+mysql的在线CRM管理系统(含LW+PPT+源码+系统演示视频+安装说明)
  • 【Bluedroid】蓝牙HID Device virtual_cable_unplug全流程源码解析
  • Pycharm-jupyternotebook不渲染
  • 运行在华为云kubernetes应用接入APM服务
  • spark任务的提交流程
  • 不同净化技术(静电 / UV / 湿式)的性能对比研究
  • 刷题记录(5)链表相关操作
  • 门店管理五大痛点解析:如何用数字化系统实现高效运营
  • HomeAssistant开源的智能家居docker快速部署实践笔记(CentOS7)
  • 在tp6模版中加减法
  • 大屏放大缩小自适应
  • 微软的 Windows Linux 子系统现已开源
  • 采集需要登录网站的教程
  • HTTP 协议的发展历程及技术演进