1

ソケットから読み取った 3 行を収集し、それらをソケットにエコーバックしようとする単純なスレッド TCP サーバーを作成しました。以下の関数 echoCommand がクラッシュします。

#include "fortunethread.h"
#include <QtNetwork>
#include <QDataStream>

FortuneThread::FortuneThread(int socketDescriptor, QObject *parent)
    : QThread(parent), socketDescriptor(socketDescriptor), in(0)
{
}

void FortuneThread::run()
{
    tcpSocketPtr = new QTcpSocket;
    if (!tcpSocketPtr->setSocketDescriptor(socketDescriptor)) {
        emit error(tcpSocketPtr->error());
        return;
    }
    in = new QDataStream(tcpSocketPtr);
    connect(tcpSocketPtr, SIGNAL(readyRead()), this, SLOT(readCommand()) );
    QThread::exec();
}

void FortuneThread::echoCommand()
{
    QString block;
    QTextStream out(&block, QIODevice::WriteOnly);
    for (QStringList::Iterator it = commandList.begin(); it != commandList.end(); ++it) {
        out << "Command: " << *it << endl;
    }

    out << endl;
    tcpSocketPtr->write(block.toUtf8());
    tcpSocketPtr->disconnectFromHost();
    tcpSocketPtr->waitForDisconnected();
}

void FortuneThread::readCommand()
{
    while (tcpSocketPtr->canReadLine())
    {
        commandList << (tcpSocketPtr->readLine()).trimmed();
    }

    if (commandList.size() > 2)
    {
        echoCommand();
    }
}

スロット/シグナルを接続するファイルは次のとおりです。

#include "fortuneserver.h"
#include "fortunethread.h"

#include <stdlib.h>

FortuneServer::FortuneServer(QObject *parent)
    : QTcpServer(parent)
{
}

void FortuneServer::incomingConnection(qintptr socketDescriptor)
{
    QString fortune = fortunes.at(qrand() % fortunes.size());
    FortuneThread *thread = new FortuneThread(socketDescriptor, this);
    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();
}

ソケットの書き込み中または書き込み後に、次のエラーが発生します。

**QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x7f19cc002720), parent's thread is FortuneThread(0x25411d0), current thread is QThread(0x220ff90)**

run() 関数で tcpSocketPtr を作成したので、この関数と同じスレッドにあることがわかります。ソケットの書き込みが失敗するのはなぜですか? telnetウィンドウに出力が表示されるので、書き込みは成功していることを指摘する必要があります...しかし、それでもソケットの書き込みは失敗します...


詳細情報...QThreadにスロットを入れるべきではないことがわかりました..これを回避する方法がわかりませんが、ここに私のクラス定義があります:

class FortuneThread : public QThread
{
    Q_OBJECT

public:
    FortuneThread(int socketDescriptor, QObject *parent);
    void run();

signals:
    void error(QTcpSocket::SocketError socketError);

private slots:
    void readCommand();

private:
    void echoCommand();
    int socketDescriptor;
    QDataStream *in;
    QStringList commandList;
    QTcpSocket *tcpSocketPtr;

};
4

0 に答える 0