QThread中未收到udp数据包

时间:2013-10-15 07:05:00

标签: c++ multithreading qt sockets qthread

我正在尝试使用我在udpReceiver单独使用qUdpSocket编写的QThread类接收一些数据包:

class udpThread : public QThread
{
private:
    QObject * parent;
public:
    udpThread(QObject * parent = 0)
    {
        this->parent = parent;
    }

    void run()
    {
        UdpReceiver * test = new UdpReceiver(parent);
    }
};


class UdpReceiver : public QObject
{
    Q_OBJECT
private:
    QUdpSocket * S;
    int port;
public:
    UdpReceiver(QObject* parent = 0) : QObject(parent)
    {
        port = 9003;
        initialize();
    }
    UdpReceiver(int p,QObject* parent = 0) : QObject(parent)
    {
        port = p;
        initialize();
    }

    void initialize()
    {
        S = new QUdpSocket();
        S->bind(port);
        S->connect(S,SIGNAL(readyRead()),this,SLOT(readPendingDiagrams()));
        qDebug() << "Waiting for UDP data from port " << port << " ... \n";
    }

public slots:
    void readPendingDiagrams()
    {
        while(S->waitForReadyRead())
        {
            QByteArray datagram;
            datagram.resize(S->pendingDatagramSize());
            QHostAddress sender;
            quint16 senderPort;

            S->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort);
            qDebug() << datagram.size() << " bytes received .... \n";
            qDebug() << " bytes received .... \n";
        }
    }
};

这是main()方法:

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);



//    UdpReceiver * net = new UdpReceiver();      

    MainWindow w;

    udpThread * ut = new udpThread();
    ut->start();

    w.show();


    return a.exec();
}

现在,当我使用udpReceiver类来获取没有QThread的数据包时,它工作正常,但是当我使用udpThread类时,它不会获取数据包或者至少raedyread()信号不会激活某些方式。 当我尝试获取没有QThread我的GUI的数据包以某种方式崩溃并且整个程序挂起时,这就是我想使用QThread的原因。 如果你能帮我解决这个问题我很感激:) 的问候,

2 个答案:

答案 0 :(得分:1)

在使用Qt中的线程时,你陷入了与许多人一样的陷阱:http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/ 继承QThread几乎几乎总是一个坏主意(参见http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html反例)。

按照以下方式更改代码,以“预期”方式执行(创建新的QThread并在moveToThread上调用QObject将其移至新主题)。您将从输出中看到创建UdpReceiver的线程与它接收数据的线程不同,这就是您想要的:

#include <QApplication>
#include <QDebug>
#include <QThread>
#include <QUdpSocket>

class UdpReceiver : public QObject
{
    Q_OBJECT
private:
    QUdpSocket * S;
    int port;
public:
    UdpReceiver(QObject* parent = 0) : QObject(parent)
    {
        qDebug() << "Construction thread:" << QThread::currentThreadId();

        port = 9003;
        initialize();
    }
    UdpReceiver(int p,QObject* parent = 0) : QObject(parent)
    {
        port = p;
        initialize();
    }

    void initialize()
    {
        S = new QUdpSocket();
        S->bind(port);
        S->connect(S,SIGNAL(readyRead()),this,SLOT(readPendingDiagrams()));
        qDebug() << "Waiting for UDP data from port " << port << " ... \n";
    }

public slots:
    void readPendingDiagrams()
    {
        qDebug() << "Reading thread:" << QThread::currentThreadId();

        while(S->waitForReadyRead())
        {
            QByteArray datagram;
            datagram.resize(S->pendingDatagramSize());
            QHostAddress sender;
            quint16 senderPort;

            S->readDatagram(datagram.data(), datagram.size(),&sender, &senderPort);
            qDebug() << datagram.size() << " bytes received .... \n";
            qDebug() << " bytes received .... \n";
        }
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QThread *t = new QThread();
    t->start();

    UdpReceiver * net = new UdpReceiver();
    net->moveToThread(t);

    return a.exec();
}

#include "main.moc"

我没有您的UI代码,所以我不知道那里有任何问题。如果你被困在那里并在评论中提及它,请随意发布另一个问题,我会尽力帮助。

答案 1 :(得分:0)

Vahid Nateghi,init代码和工作代码必须在同一个线程中运行。但是UdpReceiver的构造函数在主线程中运行,而不是运行一个readPendingDiagrams,这就是bug。试试这个:

{
    .......
    connect(ui.tableWidget, SIGNAL(itemChanged(QTableWidgetItem*)), this, SLOT(change_string(QTableWidgetItem*)));
}

void MyClass::change_string(QTableWidgetItem* input_item)
{
    if (input_item->text() != "") {
        if (input_item->text().contains(".", Qt::CaseSensitive)) {
            input_item->text().replace(".", ",", Qt::CaseSensitive);
        }
    }
}