来自
http://www.bogotobogo.com/Qt/Qt5_QTcpServer_Multithreaded_Client_Server.php
原始代码不再引用,只谈一个有意思的事情。
在多个socket连接中,可以不停的读或者写入,直到socket被断掉。
服务器代码
// myserver.h #ifndef MYSERVER_H #define MYSERVER_H #include <QTcpServer> class MyServer : public QTcpServer { Q_OBJECT public: explicit MyServer(QObject *parent = 0); void startServer(); signals: public slots: protected: void incomingConnection(qintptr socketDescriptor); }; #endif // MYSERVER_H
// myserver.cpp #include "myserver.h" #include "mythread.h" MyServer::MyServer(QObject *parent) : QTcpServer(parent) { } void MyServer::startServer() { int port = 1234; if(!this->listen(QHostAddress::Any, port)) { qDebug() << "Could not start server"; } else { qDebug() << "Listening to port " << port << "..."; } } // This function is called by QTcpServer when a new connection is available. void MyServer::incomingConnection(qintptr socketDescriptor) { // We have a new connection qDebug() << socketDescriptor << " Connecting..."; // Every new connection will be run in a newly created thread MyThread *thread = new MyThread(socketDescriptor, this); // connect signal/slot // once a thread is not needed, it will be beleted later connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); thread->start(); }
原始客户端socket连接进入后的处理
// mythread.cpp #include "mythread.h" MyThread::MyThread(qintptr ID, QObject *parent) : QThread(parent) { this->socketDescriptor = ID; } void MyThread::run() { // thread starts here qDebug() << " Thread started"; socket = new QTcpSocket(); // set the ID if(!socket->setSocketDescriptor(this->socketDescriptor)) { // something's wrong, we just emit a signal emit error(socket->error()); return; } // connect socket and signal // note - Qt::DirectConnection is used because it's multithreaded // This makes the slot to be invoked immediately, when the signal is emitted. connect(socket, SIGNAL(readyRead()), this, SLOT(readyRead()), Qt::DirectConnection); connect(socket, SIGNAL(disconnected()), this, SLOT(disconnected())); // We'll have multiple clients, we want to know which is which qDebug() << socketDescriptor << " Client connected"; // make this thread a loop, // thread will stay alive so that signal/slot to function properly // not dropped out in the middle when thread dies exec(); } void MyThread::readyRead() { // get the information QByteArray Data = socket->readAll(); // will write on server side window qDebug() << socketDescriptor << " Data in: " << Data; socket->write(Data); } void MyThread::disconnected() { qDebug() << socketDescriptor << " Disconnected"; socket->deleteLater(); exit(0); }
对mythread.cpp主要做了两部分修改
1 将这部分使用单独DataClient类,每来一个连接(incommingconnections)
则DataClient * client = new DataClient();
QThread *pt = new QThread();
client->movetoThread(pt);
2 此种情况下则无法在thread中保证exec()循环。在readRead中执行循环。
循环语句类似
while(1) { if(socket->state() == QAbstractSocket::UnconnectedState|| socket->waitForDisconnected(1000)) { break; } qDebug() << "I am client " << socketDescriptor << ", i am working"; }