Qt线程中使用Socket作为客户端通信

在编写一般程序中,通常将通信部分与数据处理部分单独放到一个线程或进程(Python由于GIL锁需要使用进程),这样可保证程序的快速响应,数据处理不会对其他部分造成影响。

在Qt中使用线程有两种方式:一种是继承QThread,重新实现run()函数。此时要注意,只有run()函数里面的才是单独运行到线程中的。通常在run()函数中使用while()循环或for循环与队列配合,让线程一直处理请求。另一种是使用moveToThread()函数将对象移到子线程中,moveToThread()函数之后再做说明,本次主要说明使用QThread时遇到的问题。

这是传说中的UI。。。 ~ ~。。。

 

 

 

一些程序:

 

#ifndef THREADSOCKET_H

#define THREADSOCKET_H

 

#include <QThread>

#include <QTcpSocket>

 

 

class ThreadSocket : public QThread

{

    Q_OBJECT

 

public:

    ThreadSocket();

 

    void start_thread();

 

public slots:

    void slot_readmesg();

    void slot_WritMsgToServer(QString str);

 

protected:

    void run();

 

private:

    QTcpSocket *mp_clsTcpSocket;

    bool couldReadData;

};

 

#endif // THREADSOCKET_H

 

#include "threadsocket.h"

#include <QDebug>

 

ThreadSocket::ThreadSocket():

    QThread(),

    couldReadData(false)

{

    qDebug() << "parent this id" << this;

}

 

void ThreadSocket::start_thread()

{

    if(!this->isRunning())

        this->start();

}

 

void ThreadSocket::slot_readMsgFromServer()

{

    couldReadData = true;

    QByteArray buffer = mp_clsTcpSocket->readAll();

    qDebug() <<"msg:"<< buffer;

 

}

 

void ThreadSocket::slot_WritMsgToServer(QString str)

{

    mp_clsTcpSocket->write(str.toLatin1());

}

 

void ThreadSocket::run()

{

    mp_clsTcpSocket = new QTcpSocket();

 

    mp_clsTcpSocket->connectToHost("192.168.18.77",2115);

    connect(mp_clsTcpSocket,SIGNAL(readyRead()),this, SLOT(slot_readMsgFromServer()));

 

    if (mp_clsTcpSocket->waitForConnected(1000))

    {

        qDebug() << "connect success !";

    }else{

        qDebug() << "connect faild !";

    }

 

    while(1)

    {

        qDebug() << "__________________";

        mp_clsTcpSocket->write("test\n");

        mp_clsTcpSocket->flush();

 

        qDebug() << "couldReadData" << couldReadData;

 

        if (true == couldReadData)

        {

            QByteArray buffer = mp_clsTcpSocket->readAll();

            qDebug() <<"receive server msg:"<< buffer;

 

            couldReadData = false;

        }

 

        sleep(1);

②//        exec();

 

    }

 

}

 

简单说下程序构成:所贴代码主要是线程中的socket接收与发送测试代码。主UI中有两个按钮,一个是启动线程,另一个是在通过信号槽向服务器发送数据。

在run()函数中实例化客户端,注意不要传入this指针,否则会报如下错误:QObject: Cannot create children for a parent that is in a different thread.【QObject:无法为位于不同线程中的父级创建子级。】

这样客户端就存在与子线程中,同样在run()中连接信号和槽。注意此时的this是父类的this,即信号与槽位于不同的线程。这是第一个值得注意的地方。

第二该测试中,需要在客户端write()后加flush(),否则客户端无法发送数据。这是第二个需要注意的地方。

第一种测试:

运行该测试程序,可以在run()中向服务器发送数据,但是无法在主UI通过信号和槽的方式向服务器发送数据。点击Send按钮,报错如下:QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread.【QSocketNotifier:无法从另一个线程启用或禁用套接字通知程序】。服务器向客户端发送数据,客户端接收不到,connect()函数返回True,说明信号与槽连接成功。这是上述测试程序的运行结果。

第二种测试:

在sleep(1)后加入 exec()函数,while()循环只执行一次,客户端槽函数可以接收服务器发出的数据。但在主UI中依然无法向服务器发送数据。

这次的内容只描述两种测试结果,接下来的其他内容将逐步剖析这些情况的原因。

一起学习,共同进步。我们都是奋斗者!

 

***********************    update   *******  2019 09 07********************

结论也就是无法通过这种方式在线程中使用socket。不过可以通过moveToThread的方式实现:

qt线程中使用socket的正确打开方式

***********************    update   *******  2019 09 07********************

 

欢迎大家关注我的公众号!

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值