Qt如何实现tcp通信?(三)
在《Qt如何实现tcp通信?(二)》中说到重写QTcpServer的incomingConnection函数得到qintptr类型的变量。通过它可以实现多线程的服务端,那么该如何实现多线程呢? 说到多线程很自然会想到QThread。
通过继承QThread,重写run函数。然后在run函数里创建socket。
.h文件:
#include <QThread> #include <QTcpSocket> class ServerSocket : public QThread { Q_OBJECT public: ServerSocket(qintptr handle, QObject *parent = 0); protected: void run(); private slots: void slotReadyRead(); private: qintptr m_handle; QTcpSocket* m_socket; }; #endif // SERVERSOCKET_H
.cpp文件:
#include "serversocket.h" #include <qDebug> ServerSocket::ServerSocket(qintptr handle,QObject *parent):QThread(parent) { m_handle = handle; } void ServerSocket::run() { m_socket = new QTcpSocket; m_socket->setSocketDescriptor(m_handle); connect(m_socket,SIGNAL(readyRead()),this,SLOT(slotReadyRead())); exec(); } void ServerSocket::slotReadyRead() { qDebug()<<"server recv-->"<<QString(m_socket->readAll()); }
incomingConnection函数:
void MyServer::incomingConnection(qintptr handle) { ServerSocket* socket = new ServerSocket(handle); socket->start(); }
首先添加了一个ServerSocket类,从QThread派生下来。在它的构造函数中保存了qintptr handle变量,然后在run函数中创建一个QTcpSocket,接着setSocketDescriptor。可想而知socket是在子线程中的。在run函数的最底下调用了exec()防止子线程结束了。
我们在TcpServer的incomingConnection函数中创建了一个ServerSocket并启动,表示每次来一个连接就创建一个线程。我们用客户端连接该服务端并发送数据,会发现slotReadyRead()收到了数据。
是不是有点小激动?既然收到了客户端的信息,作为礼貌应该回复一下,于是在读取数据后发送一条信息,像这样:
void ServerSocket::slotReadyRead() { qDebug()<<"server recv-->"<<QString(m_socket->readAll()); m_socket->write("hello client"); }
再运行一次,服务端报错了:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QNativeSocketEngine(0x209db5994b0), parent's thread is ServerSocket(0x209db5a5640), current thread is QThread(0x209db5348f0)
是的,报了个线程的问题。m_socket在子线程,但是slotReadyRead()是在主线程。光顾着把socket放子线程去,没想到write也要和socket在一个线程里。 事实上,回过头来看readAll也是在主线程中执行的,所以根本就没有达到多线程的目的。看来这种方式不可行。
相关文章: