QT QTcpServer::incomingConnection(qintptr handle) 不触发? [英] QT QTcpServer::incomingConnection(qintptr handle) not firing?

查看:94
本文介绍了QT QTcpServer::incomingConnection(qintptr handle) 不触发?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次尝试使用 Qt 创建多线程服务器.通常,人们会使用 QTcpServer::nextPendingConnection() 返回的套接字指针,并且套接字句柄已经内置 - 但是由于我在单独的线程上与连接客户端进行交互,因此我需要创建使用 QTcpServer::incomingConnection(qintptr handle) 中的 qintptr handle 单独连接套接字.经过一个非常沉闷,错误包装的调试会话后,我设法将问题追溯到 QTcpServer::incomingConnection() 从未被解雇?

I'm trying to create a multithreaded server using Qt for the first time. Normally one would use the socket pointer returned by the QTcpServer::nextPendingConnection() with the socket handle already baked in - but since I'm interfacing with the connecting client on a separate thread, I need to create the socket separately using the qintptr handle from QTcpServer::incomingConnection(qintptr handle). After a very dreary, error-packed debugging session I managed to track down the problem to the QTcpServer::incomingConnection() never being fired?

有没有人遇到过类似的问题 - 最近版本的 Qt 有什么变化吗?

Has anyone had a similar problem - has something changed over recent versions Qt?

这些是我尝试过的:

  • QTcpServer::incomingConnection(qintptr 句柄)
  • QTcpServer::incomingConnection(qintptr socketDescriptor)
  • QTcpServer::incomingConnection(int handle)

创建服务器实例:

TestServer *myServer = new TestServer();
myServer->initializeServer(1234);

调用:

void TestServer::initializeServer(quint16 port)
{

mainServer = new QTcpServer(this);

mainServer->listen(QHostAddress::Any, port);

qDebug() << "Listening for connections on port: " << port;



}

服务器正在监听.当客户端连接incomingConnection(qintptr handle)应该被调用:

Server is now listening. When a client connects incomingConnection(qintptr handle) is supposed to be called:

void TestServer::incomingConnection(qintptr socketDescriptor){

TestClient *client = new TestClient(this);
client->setSocket(socketDescriptor);

}

调用:

void TestClient::setSocket(quint16 socketDescr)
{
socket = new QTcpSocket(this);

socket->setSocketDescriptor(socketDescr);

connect(socket, SIGNAL(connected()),this,SLOT(connected()));
connect(socket, SIGNAL(disconnected()),this,SLOT(disconnected()));
connect(socket, SIGNAL(readyRead()),this,SLOT(readyRead()));



}

调用 connect() 信号:

Called on connect() signal:

void TestClient::connected()
{   
qDebug() << "Client connected..."; // This debug never appears in the console, since QTcpServer::incomingConnection isn't being fired.

}

推荐答案

你的代码有一些错误:

  1. TestServer,您的QTcpServer 可能已聚合,但您需要继承它.在这种情况下,您尝试覆盖 incomingConnection() 方法,但您没有基类,您只是创建新的 incomingConnection(),而不是覆盖.
  2. 您从 incomingConnection() 获得 qintptr 描述符 变量,但在 setSocket() 方法中设置 quint16 类型.
  3. 您可能将服务器客户端和您的客户端混合在一起,它们只是获取传入的连接并处理套接字数据.
  1. At TestServer your QTcpServer probably aggregated, but you need to inherit it. At this case you try to override incomingConnection() method, but you haven't base class and you just create new incomingConnection(), not override.
  2. You get qintptr descriptor variable from incomingConnection(), but set quint16 type at setSocket() method.
  3. You probably mix client of server and client of your part, which just get incoming connection and handling socket data.

我在下面写了一些小例子,让你理解 tcp 客户端-服务器通信.

I write some little example below for your understanding tcp client-server communication.

服务器部分

主要部分是服务器本身:

Main part is server themselves:

#include <QTcpServer>

class TestServer: public QTcpServer
{
public:
    TestServer(QObject *parent = 0);
    void incomingConnection(qintptr handle) Q_DECL_OVERRIDE;
};

看看吧:我不聚合QTcpServer,但继承了它.在这种情况下,您可以覆盖 incomingConnection() 方法正确.在构造函数中,我们只是使用 listen() 启动服务器进行侦听 方法:

Just look: I don't aggragate QTcpServer, but inherited it. At this case you can override incomingConnection() method correctly. At constructor we just start server for listening using listen() method:

TestServer::TestServer(QObject *parent):
    QTcpServer(parent)
{
    if (this->listen(QHostAddress::Any, 2323)) {
        qDebug() << "Server start at port: " << this->serverPort();
    } else {
        qDebug() << "Start failure";
    }
}

然后是重写incomingConnection()的时间:

void TestServer::incomingConnection(qintptr handle)
{
    qDebug() << Q_FUNC_INFO << " new connection";
    SocketThread *socket = new SocketThread(handle);

    connect(socket, SIGNAL(finished()), socket, SLOT(deleteLater()));
    socket->start();
}

我创建了处理传入数据的 SocketThread 对象:

I create SocketThread object which handle incoming data:

#include <QThread>
#include <QObject>

class QTcpSocket;

class SocketThread: public QThread
{
    Q_OBJECT
public:
    SocketThread(qintptr descriptor, QObject *parent = 0);
    ~SocketThread();

protected:
    void run() Q_DECL_OVERRIDE;

private slots:
    void onConnected();
    void onReadyRead();
    void onDisconnected();

private:
    QTcpSocket *m_socket;
    qintptr m_descriptor;
};

我们从 QThread 继承来使我们的服务器多线程,所以我们必须覆盖 run() 方法:

We inherits from QThread for making our server multithreading, so we have to override run() method:

SocketThread::SocketThread(qintptr descriptor, QObject *parent)
    :  QThread(parent), m_descriptor(descriptor)
{

}

void SocketThread::run()
{
    qDebug() << Q_FUNC_INFO;
    m_socket = new QTcpSocket;
    m_socket->setSocketDescriptor(m_descriptor);

    connect(m_socket, SIGNAL(readyRead()),    this, SLOT(onReadyRead()), Qt::DirectConnection);
    connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()), Qt::DirectConnection);

    exec();
}

这样我们就初始化了我们的QTcpSocket,设置套接字描述符,将其与 readyRead()disconnected() 信号和启动事件循环.

This way we initialize our QTcpSocket, set socket descriptor, connect it with readyRead() and disconnected() signals and start event loop.

void SocketThread::onReadyRead()
{
    QDataStream in(m_socket);
    in.setVersion(QDataStream::Qt_5_5);

    QString message;
    in >> message;
    qDebug() << message;

    m_socket->disconnectFromHost();
}

void SocketThread::onDisconnected()
{
    m_socket->close();
    // Exit event loop
    quit();
}

onReadyRead() 处,只需从客户端读取一些QString,将其写入控制台并断开与主机的连接.在 onDisconnected() 我们关闭套接字连接并退出事件循环.

At onReadyRead() just read some QString from client, write it to console and disconnect from host. At onDisconnected() we close socket connection and exit event loop.

客户端部分

这只是示例和难闻的风格,但我在 QPushButton::clicked 信号的 MainWindow 类上创建了到服务器的连接:

It is just example and bad-smells style, but i create connection to the server at MainWindow class on QPushButton::clicked signal:

void MainWindow::on_pushButton_clicked()
{
    QTcpSocket *client = new QTcpSocket;
    connect(client, SIGNAL(connected()), this, SLOT(connected()));
    connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater()));

    client->connectToHost(QHostAddress::LocalHost, 2323);
    client->waitForConnected();

    if (client->state() != QAbstractSocket::ConnectedState ) {
        qDebug() << Q_FUNC_INFO << " can't connect to host";
        delete client;
        return;
    }
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_5);
    out << QString("Hello");
    out.device()->seek(0);
    client->write(block);
}

void MainWindow::connected()
{
    qDebug() << Q_FUNC_INFO << " client connected";
}

我创建了新的 QTcpSocket,将它连接到信号并尝试连接到主机(在我的情况下它是本地主机).等待连接并检查套接字状态.如果一切正常,我将写入套接字 QString - 只是示例.

I create new QTcpSocket, connect it to the signals and try to connect to the host(in my case it is localhost). Wait for connected and check socket status. If all is right I write to socket QString - just example.

这是组织多线程客户端-服务器架构的一种可能方法,希望对您有所帮助,并找到您的错误.

It is one of possible ways to organized multithreading client-server architecture, i hope it will be helpfull for you and you find yours bugs.

这篇关于QT QTcpServer::incomingConnection(qintptr handle) 不触发?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆