我试图通过使用QRunnable和QThreadPool而不是每个连接1个线程,以可扩展的方式使用Qt 5.2编写tcp服务器。

我遇到的问题是,在我创建并设置其套接字描述符时,在QRunnable :: run中创建的套接字具有连接状态,但是即使对readyRead信号进行响应,调用readAll()也会产生一个空缓冲区,即使我知道我发送了一些数据。

我尝试将套接字从主线程传递到QRunnable的两种方法是:

1)从QTcpServer :: nextPendingConnection获取QTcpSocket并将套接字描述符传递给QRunnable。

2)重写QTcpServer :: incomingConnection并从那里获取套接字描述符,并将其传递给QRunnable。

两者都给出相同的结果,接收到套接字readyread信号,但readAll返回一个空缓冲区。

任何帮助将不胜感激。

最佳答案

感谢RobbieE纠正了我的误会。这是一个如何编写使用QRunnables和QThreadpool的Tcp服务器的工作示例。我是Qt的新手,欢迎任何批评/改进/讨论。该代码并非旨在提高产品质量,仅是编写可伸缩tcp服务器的一种简单示例。

#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();
}


服务器

#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";

}

10-06 14:58