Qt线程中使用socket作为客户端通信(二)

Qt使用线程的方式有两种,一种是上次所说的继承QThread重新实现run()函数,在run()函数中一直循环处理;另一种则是继承QObject并使用moveToThread()函数将对象移到子线程中。由于继承QThread方式使用的并不规范,Qt官方强烈建议使用继承QObject的方式。

根据之前编写程序得到的结果,在相对复杂的UI设计中,如果socket通信放在住UI中,并且让服务器每间隔10ms发送数据,这样会影响UI的响应,所以应将socket接收数据部分放到线程中。由上次程序得出的结果,使用继承QThread的方式并不可行,所以这次使用继承QObject的形式。经测试得出,继承QObject该方式不会造成UI的卡顿。

下面直接贴段代码压压惊:

客户端.h部分:

#ifndef MYCLIENT_H

#define MYCLIENT_H

 

#include <QObject>

#include <QThread>

class QTcpSocket;

 

class MyClient : public QObject

{

    Q_OBJECT

public:

    explicit MyClient(QObject *parent = 0);

 

    bool connectServer();

    void writeMsgToServer(QString str);

 

signals:

 

public slots:

    void slot_readMsgFromServer();

 

private:

    QTcpSocket *mp_clsTcpSocket;

};

 

#endif // MYCLIENT_H

 

客户端.cpp部分:

#include "myclient.h"

#include <QTcpSocket>

 

MyClient::MyClient(QObject *parent) : QObject(parent)

{

    mp_clsTcpSocket = new QTcpSocket;

 

    connect(mp_clsTcpSocket, SIGNAL(readyRead()),        //Qt::QueuedConnection

            this, SLOT(slot_readMsgFromServer()));

}

 

bool MyClient::connectServer()

{

    mp_clsTcpSocket->connectToHost("192.168.18.77",2115);//Qt::BlockingQueuedConnection

 

    if (mp_clsTcpSocket->waitForConnected(1000))

    {

        qDebug() << "connect success !";

        return true;

    }else{

        qDebug() << "connect faild !";

        return false;

    }

 

}

 

void MyClient::writeMsgToServer(QString str)

{

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

}

 

void MyClient::slot_readMsgFromServer()

{

    QByteArray recMsg = mp_clsTcpSocket->readAll();

    qDebug() << "recMsg from Server:" << recMsg;

}

 

为测试,IP和port直接使用固定的。

UI部分简要程序:

 

MyClient *mp_clsClient;

QThread *mp_thread;

 

Widget构造函数部分:

mp_thread= new QThread;

mp_clsClient = new MyClient();

mp_clsClient->connectServer();

mp_clsClient->moveToThread(mp_thread);

 

 

StartThread按钮:

mp_thread->start();

 

Send按钮:

mp_clsClient->writeMsgToServer(ui->lineEdit->text().append("\n"));

 

结果如图:

 

服务器端:

 

 

以目前我的知识水平来讲,之前在Qt线程中使用socket的方法是不正确的。如果以后遇到新的解决方式,会重新更新!

 

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

以上的内容是错误的,老铁们不要被误导,正确方式如下:

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

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

如果觉得还阔以,请关注~~~

 

Qt,可以通过QTcpServer类来实现TCP服务器的编写,而多线程则可以通过QThread类来实现。下面是一个简单的示例程序,可以实现多线程与多个客户端通信: ```cpp #include <QtNetwork> #include <QtWidgets> #include <QtCore> class ClientThread : public QThread { Q_OBJECT public: explicit ClientThread(qintptr socketDescriptor, QObject *parent = nullptr) : QThread(parent), m_socketDescriptor(socketDescriptor) { } signals: void error(QTcpSocket::SocketError socketError); protected: void run() override { QTcpSocket socket; if (!socket.setSocketDescriptor(m_socketDescriptor)) { emit error(socket.error()); return; } connect(&socket, &QTcpSocket::readyRead, this, &ClientThread::readyRead); connect(&socket, &QTcpSocket::disconnected, this, &ClientThread::disconnected); exec(); } private slots: void readyRead() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (!socket) return; QByteArray data = socket->readAll(); // 处理接收到的数据 socket->flush(); } void disconnected() { QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender()); if (!socket) return; socket->deleteLater(); quit(); } private: qintptr m_socketDescriptor; }; class TcpServer : public QTcpServer { Q_OBJECT public: TcpServer(QObject *parent = nullptr) : QTcpServer(parent) { } protected: void incomingConnection(qintptr socketDescriptor) override { ClientThread *thread = new ClientThread(socketDescriptor, this); connect(thread, &ClientThread::finished, thread, &ClientThread::deleteLater); thread->start(); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); TcpServer server; if (!server.listen(QHostAddress::Any, 1234)) { qCritical() << "Failed to start server:" << server.errorString(); return 1; } qDebug() << "Server started:" << server.serverAddress().toString() << server.serverPort(); return app.exec(); } #include "main.moc" ``` 在这个示例程序,TcpServer类继承自QTcpServer类,其的incomingConnection()函数会在新的客户端连接时被调用。在该函数,我们创建一个新的ClientThread线程,并将客户端socket描述符传递给它。在ClientThread线程,我们可以通过QTcpSocket类来与客户端进行通信。当客户端连接断开时,我们需要清理socket并退出线程。 需要注意的是,由于Qt的对象树模型,我们需要在ClientThread线程使用deleteLater()函数来删除socket对象。这可以确保socket对象不会在其所属的线程销毁之前被销毁。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值