gpt4 book ai didi

qt - 如何通过QTcpSocket接收结构?

转载 作者:行者123 更新时间:2023-12-03 11:58:04 24 4
gpt4 key购买 nike

我想使用QTCPSocket发送和接收结构。

该系统确实具有中央套接字服务器和许多Qt客户端应用程序。
每个客户端发送一个结构,该结构由中央套接字服务器广播给其余部分。
Connector扩展QTcpSocket
这是我的连接方法

void Connector::Open(QString address, int port) // It works!
{
connectToHost(address, port);
this->onWaiting();

connect(this, SIGNAL(connected()), this, SLOT(connected()));
connect(this, SIGNAL(disconnected()), this, SLOT(disconnected()));
connect(this, SIGNAL(readyRead()), this, SLOT(readyRead()));
connect(this, SIGNAL(bytesWritten(qint64)), this, SLOT(bytesWritten(qint64)));
}

这是我发送数据的方法
void Connector::SendData(const void* data,qint64 len) // It works!
{
writeData((char*)data,len);
waitForBytesWritten();
}

这是为了接收
void Connector::readyRead()  // Don't work
{
Information n; //My struct
memcpy(&n, data.data(), data.size());
onInformationReceived(n);
}

但是收到的信息始终是无效的。那是对的吗?

最佳答案

有一些问题:

  • 可以使用任意数量的可读取字节来调用readyRead()插槽。您唯一的保证是它的字节数大于零,尽管实际上没有理由指望它。您必须检查bytesAvailable。可以是一个字节。可以是一个兆字节。

    参见例如this answerthat answer用于叙述,而that one用于代码。

    至少,您需要:
    void Connector::readyRead() {
    if (bytesAvailable() < sizeof(Information)) return;
    Information info;
    auto const data = read(sizeof(Information));
    memcpy(&info, data.constData(), data.size());
    onInformationReceived(info);
    }
  • 无法通过网络将struct作为不透明的二进制文件发送。无法保证接收端将以相同的方式对结构进行布局。除非引用编译器ABI文档,否则您甚至都不知道数据的二进制格式。

    参见例如this answer,了解如何正确执行操作。

    至少,您需要为QDataStream实现Information流运算符,然后在连接的两端使用它:
    QDataStream & operator<<(QDataStream &, const Information &);
    QDataStream & operator>>(QDataStream &, Information &);

    void Connector::send(const Information & info) {
    auto dev = this; // We're a QIODevice :(
    QDataStream stream{dev};
    stream << info;
    dev.waitForBytesWritten(); // this is superbly bad!
    }

    void Connector::readyRead() {
    auto dev = this; // We're a QIODevice :(
    QDataStream stream{dev};
    stream.startTransaction();
    Information info;
    dev >> info;
    if (! stream.commitTransaction()) return;
    onInformationReceived(info);
    }
  • 您不应该扩展QTcpSocket。您的类(class)应该是一个QObject,按值保存一个QTcpSocket
  • 您永远不要阻塞。

  • 因此,固定的 Connector类可能如下所示。再次, this answer描述了如何正确使用 QDataStream来说明与代码的将来更新的兼容性。另请参阅 this answer,了解如何利用Qt 5.7的 QDataStream中的读取事务。
    class Connector : public QObject {
    Q_OBJECT
    QTcpDevice m_dev;
    QDataStream m_str{&m_dev};
    void onReadyRead() {
    m_str.startTransaction();
    Information info;
    m_str >> info;
    if (! stream.commitTransaction()) return;
    onInformationReceived(info);
    }
    void onBytesWritten() {
    if (m_dev.bytesToWrite() == 0)
    emit allDataSent();
    }
    void onInformationReceived(const Information &);
    public:
    Connector(const QString & address, int port, QObject * parent = nullptr) :
    QObject{parent}
    {
    connect(&m_dev, &QAbstractSocket::connected, this, &Connector::connected);
    connect(&m_dev, &QAbstractSocket::disconnected, this, &Connector::disconnected);
    connect(&m_dev, &QIODevice::readyRead, this, onReadyRead);
    connect(&m_dev, &QIODevice::bytesWritten, this, onBytesWritten);
    m_dev.connect(address, port);
    }
    void send(const Information & info) {
    m_str << info;
    }
    Q_SIGNAL void connected();
    Q_SIGNAL void disconnected();
    Q_SIGNAL void allDataSent();
    }

    关于qt - 如何通过QTcpSocket接收结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39167758/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com