Qt笔记-QTcpSocket跨线程调用(官方推荐方法,非百度烂大街方法)

Posted IT1995

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt笔记-QTcpSocket跨线程调用(官方推荐方法,非百度烂大街方法)相关的知识,希望对你有一定的参考价值。

TCP服务端的经典案例中有个例子,就是当收到TCP客户端连接后,线程池直接开一个线程然后把这个socket指针传到线程里面,依靠新开的线程进程业务处理。

但在Qt里面使用这个方式后,会报一个QTcpSocket不能跨线程调用的问题。

问题描述是这样的:

QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

查了下百度,都是n年前的技术(本博文写于2021-08-11 09:15:25,此博文发布到网上应该是1个月以后,笔记太多了,每星期公布6篇笔记),用信号与槽机制将业务处理放到新线程中,TCP操作用信号让以前的线程发送数据,通过这种方式解决问题!但如果这样做,代码就不够优雅了,甚至还有点烂。一个新技术框架和老技术做对比,应该是取其精华去其糟粕,而不是越来越复杂。不然这个新技术将毫无意义。

花了半天时间查阅了官方资料,最后得出了QTcpSocket跨线程调用的方式。

首先继承QTcpServer重写incomingConnection(qintptr handle)

 

当这个handle此时套接字的描述符号。把这个传给线程,子线程生成一个QTcpScoket然后利用setSocketDescriptor使得这个socket获得到收发数据的能力。

实例如下:

QTcpServer相关:

void HttpsServer::incomingConnection(qintptr socketDescriptor)
{
    QThreadPool::globalInstance()->start(new HttpsThread(socketDescriptor));
}

QRunnable相关:

HttpsThread::HttpsThread(qintptr descriptor)
{
    m_socketDescriptor = descriptor;
}

这个m_socketDescriptor直接为int型就可以了。

这样run()中调用setSocketDescriptor,进行读写操作就不会有跨线程的问题了。

void HttpsThread::run()
{
    QTcpSocket tcpSocket;
    if(!tcpSocket.setSocketDescriptor(m_socketDescriptor)) {

        qDebug() << "tcpSocket.setSocketDescriptor(m_socketDescriptor) failed";
        return;
    }

    tcpSocket.write("Hello Wold");

    tcpSocket.disconnectFromHost();
    tcpSocket.waitForDisconnected();
}

以上是关于Qt笔记-QTcpSocket跨线程调用(官方推荐方法,非百度烂大街方法)的主要内容,如果未能解决你的问题,请参考以下文章

Qt笔记-QTcpSocket中调用readAll要注意的地方(Java中RestTemplate和Qt配合要注意的地方)

Qt笔记-QTcpSocket中调用readAll要注意的地方(Java中RestTemplate和Qt配合要注意的地方)

从来自 QTcpSocket 的数据流中连续运行复杂算法的最佳 Qt 线程解决方案是啥?

我从 QThread 调用 QTcpSocket 类的写入函数时出现错误

Qt跨线程调用错误解析及解决办法

Qt笔记-解决QTcpSocket发送数据成功,但接收端接收不全的问