QT开发中文网

给我一个使用QByteArray 作为TCP数据包的解析案例 并给出分包 粘包代码

当使用 QByteArray 作为TCP数据包时,常见的问题是粘包和分包。下面给出一个示例代码,演示如何处理TCP数据包的粘包和分包情况:

class TcpServer : public QTcpServer
{
    Q_OBJECT

public:
    explicit TcpServer(QObject* parent = nullptr) : QTcpServer(parent) {}

protected:
    void incomingConnection(qintptr socketDescriptor) override
    {
        TcpSocket* socket = new TcpSocket(this);
        if (socket->setSocketDescriptor(socketDescriptor)) {
            connect(socket, &TcpSocket::readyRead, this, &TcpServer::processReadyRead);
            connect(socket, &TcpSocket::disconnected, this, &TcpServer::removeSocket);

            m_sockets.append(socket);
        } else {
            delete socket;
        }
    }

private slots:
    void processReadyRead()
    {
        TcpSocket* socket = qobject_cast<TcpSocket*>(sender());
        if (!socket)
            return;

        QByteArray buffer = socket->readAll();
        m_receiveBuffer.append(buffer);

        while (true) {
            // 检查接收缓冲区中是否有足够的数据可以解析
            if (m_receiveBuffer.size() < 4)
                break;

            quint16 header = qFromBigEndian<quint16>(reinterpret_cast<const uchar*>(m_receiveBuffer.constData()));
            quint16 dataLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar*>(m_receiveBuffer.constData() + 2));

            // 检查接收缓冲区中是否有完整的数据包
            if (m_receiveBuffer.size() < 4 + dataLength)
                break;

            QByteArray packetData = m_receiveBuffer.mid(4, dataLength);
            m_receiveBuffer = m_receiveBuffer.mid(4 + dataLength);

            // 对提取出来的packetData进行处理或解析
            processPacketData(packetData);
        }
    }

    void removeSocket()
    {
        TcpSocket* socket = qobject_cast<TcpSocket*>(sender());
        if (!socket)
            return;

        m_sockets.removeOne(socket);
        socket->deleteLater();
    }

private:
    QList<TcpSocket*> m_sockets;
    QByteArray m_receiveBuffer;

    void processPacketData(const QByteArray& packetData)
    {
        // 在这里对接收到的完整数据包进行处理或解析
        qDebug() << "Received packet: " << packetData;
    }
};

class TcpSocket : public QTcpSocket
{
    Q_OBJECT

public:
    explicit TcpSocket(QObject* parent = nullptr) : QTcpSocket(parent) {}

signals:
    void readyRead();

protected:
     void incomingConnection(qintptr socketDescriptor) override
     {
         emit readyRead();
     }
};

在上述代码中,我们使用了一个自定义的 TcpServer 类继承自 QTcpServer,并监听传入的连接。每当有新连接进来时,会创建一个 TcpSocket 对象,并将其添加到管理列表中。

TcpServer 中的槽函数 processReadyRead() 中,我们首先读取到可用数据后将其追加到接收缓冲区 m_receiveBuffer 中。然后,通过循环不断尝试解析数据包:检查缓冲区是否有足够长度(至少4个字节)以及是否有完整的数据包,如果满足条件,则提取出数据并将其从接收缓冲区中移除。最后,我们对提取出来的数据包调用 processPacketData() 进行处理。

需要注意的是,在示例代码中,我们使用了自定义的 TcpSocket 类继承自 QTcpSocket,并重写了 incomingConnection() 方法。这样可以通过发射 readyRead() 信号触发 processReadyRead() 槽函数,以便及时处理接收到的数据。

以上就是一个简单的TCP粘包和分包处理的示例代码,具体实现仍然需要根据你的需求进行适当修改和调整。


内容由零声教学AI助手提供,问题来源于学员提问

本站部分文章来源于网络,版权归原作者所有,如有侵权请联系站长删除。
转载请注明出处:https://qt.0voice.com/?id=11652

分享:
扫描分享到社交APP
上一篇
下一篇
发表列表
游客 游客
此处应有掌声~
评论列表

还没有评论,快来说点什么吧~

联系我们

在线咨询: 点击这里给我发消息

微信号:3007537140

上班时间: 10:30-22:30

关注我们
x

注册

已经有帐号?