Thanks to RobbieE for correcting my misunderstanding. Here is a working example of how a Tcp Server using QRunnables and a QThreadpool can be written. I'm new to Qt so any criticisms/improvements/discussion welcomed. The code isn't intended to be production quality, only a simple example of a way you can go about writing a scalable tcp server.
#include <QCoreApplication>
#include "server.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Server server;
if(server.Start())
{
qDebug() << "Server started" ;
}
else
{
qDebug() << "Server Failed to start" ;
}
return a.exec();
}
server.h
#ifndef SERVER_H
#define SERVER_H
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
class Server : public QObject
{
Q_OBJECT
public:
explicit Server(QObject *parent = 0);
bool Start();
signals:
public slots:
void onNewConnection();
private:
QTcpServer* m_pServer;
};
#endif // SERVER_H
server.cpp
#include "server.h"
#include "myrunnable.h"
#include <QThreadPool>
Server::Server(QObject *parent) :
QObject(parent)
{
m_pServer = new QTcpServer(this);
}
bool Server::Start()
{
bool bOK = true;
if(m_pServer->listen(QHostAddress::Any,1971))
{
connect(m_pServer,SIGNAL(newConnection()),this,SLOT(onNewConnection()));
}
else
{
qDebug() << "Failed to start listening";
bOK = false;
}
return bOK;
}
void Server::onNewConnection()
{
qDebug() << "onNewConnection";
QTcpSocket* pSocket = m_pServer->nextPendingConnection();
qintptr descriptor = pSocket->socketDescriptor();
MyRunnable* pRunnable = new MyRunnable();
pRunnable->setAutoDelete(true);
pRunnable->setDescriptor(descriptor);
QThreadPool::globalInstance()->start(pRunnable);
}
myrunnable.h
#ifndef MYRUNNABLE_H
#define MYRUNNABLE_H
#include <QObject>
#include <QTcpSocket>
#include <QRunnable>
#include <QEventLoop>
class MyRunnable : public QObject, public QRunnable
{
Q_OBJECT
public:
explicit MyRunnable(QObject *parent = 0);
~MyRunnable();
void run();
void setDescriptor(qintptr descriptor);
signals:
public slots:
void onConnected();
void onDisconnect();
void onReadyRead();
private:
qintptr m_socketDecriptor;
QTcpSocket* m_pSocket;
QEventLoop* m_pEventLoop;
};
#endif // MYRUNNABLE_H
myrunnable.cpp
#include "myrunnable.h"
#include <QEventLoop>
#include <QThread>
MyRunnable::MyRunnable(QObject *parent) :
QObject(parent),m_pSocket(0)
{
}
MyRunnable::~MyRunnable()
{
qDebug() << "MyRunnable destructor called";
}
void MyRunnable::run()
{
m_pEventLoop = new QEventLoop();
m_pSocket = new QTcpSocket();
if(m_pSocket->setSocketDescriptor(m_socketDecriptor))
{
connect(m_pSocket,SIGNAL(connected()),this,SLOT(onConnected()),Qt::QueuedConnection);
connect(m_pSocket,SIGNAL(disconnected()),this,SLOT(onDisconnect()),Qt::QueuedConnection);
connect(m_pSocket,SIGNAL(readyRead()),this,SLOT(onReadyRead()),Qt::QueuedConnection);
}
m_pEventLoop->exec();
delete m_pSocket;
delete m_pEventLoop;
}
void MyRunnable::setDescriptor(qintptr descriptor)
{
m_socketDecriptor = descriptor;
}
void MyRunnable::onConnected()
{
qDebug() << "Connected";
}
void MyRunnable::onDisconnect()
{
qDebug() << "Disconnected";
//m_pEventLoop->disconnect();
m_pEventLoop->exit();
}
void MyRunnable::onReadyRead()
{
qDebug() << m_pSocket->readAll();
for(int i=0;i<4;i++)
{
qDebug() << "Sleeping for 5 seconds to simulate work being done.\r\n";
QThread::sleep(5);
qDebug() << "...\r\n";
}
//qDebug() << "OnReadReady";
}
QEventLoop
. – RobbieE