c++ - 子类化 QTcpServer 时,如何延迟发出 newConnection() 信号?

标签 c++ qt ssl qtcpserver qt-signals

我想创建一个 SSL 服务器,所以我继承了 QTcpServer 并覆盖了 incomingConnection() ,我在这里创建了一个 QSslSocket , 设置它的描述符,然后调用 QSslSocket::startServerEncryption .此时我需要等待 QSslSocket::encrypted()要发出的信号,只有在那之后我的服务器才会发出 newConnection()信号。客户端代码会认为它正在使用 QTcpSocket,但实际上会使用安全套接字。

但是QTcpServer 总是发出 newConnection()打电话后 incomingConnection() (我查看了 the source of QTcpServer ):

void QTcpServerPrivate::readNotification()
{
    // .........
        q->incomingConnection(descriptor);
        QPointer<QTcpServer> that = q;
        emit q->newConnection();
    // .........
}

所以我的问题是,有什么方法可以防止 QTcpServer从发射 newConnection() ,直到我准备好自己发射它?

我想要这个的原因是我希望我的类能够被用作 QTcpServer 的直接替代品,通过不知道它正在使用它的代码,所以它必须完全像 QTcpServer 一样工作:

QTcpServer* getServer(bool ssl)
{
    return ssl ? new SslServer : new QTcpServer;
}

我的 SslServer 类代码目前是这样的:

void SslServer::ready()
{
    QSslSocket *socket = (QSslSocket *) sender();
    addPendingConnection(socket);
    emit newConnection();
}

void SslServer::incomingConnection(int socketDescriptor)
{
    QSslSocket *serverSocket = new QSslSocket;
    if (serverSocket->setSocketDescriptor(socketDescriptor)) {
        connect(serverSocket, SIGNAL(encrypted()), this, SLOT(ready()));
        serverSocket->startServerEncryption();
    } else {
        delete serverSocket;
    }
}

最佳答案

这里有一个在这种情况下可行的想法:在您的 QTcpServer 子类中重新定义 newConnection 信号。

如果这样做,与服务器实例连接的对象将不会收到 QTcpServer 的信号“版本”,只会收到您直接从子类发出的信号。

这是一个概念证明:A 类是 QTcpServerfoo 是您试图“劫持”的信号,bar 只是您不需要触摸的 QTcpServer 的另一个(假设的)信号。

class A: public QObject
{
    Q_OBJECT
    public:
        A() {};
        virtual void doit() {
            qDebug() << "A::doit";
            emit foo(1);
            emit bar(1);
        }
    signals:
        void foo(int);
        void bar(int);
};

Class B 是您的子类。请注意,它重新定义了信号 foo,但没有对 bar 做任何事情。

class B: public A
{
    Q_OBJECT
    public:
        B() {};
        virtual void doit() {
            qDebug() << "B::doit";
            emit foo(2);
            emit bar(2);
        }
    signals:
        void foo(int);
};

C 类是一个潜在的客户端,它连接来自 B 实例的信号/槽,就像连接 A 实例一样。

class C: public QObject
{
    Q_OBJECT
    public:
        C() {
            B *b = new B;
            connect(b, SIGNAL(foo(int)), this, SLOT(foo(int)));
            connect(b, SIGNAL(bar(int)), this, SLOT(bar(int)));
            /* 1 */
            b->doit();
            /* 2 */
            b->A::doit(); // call parent class's function
        };
    public slots:
        void foo(int i) {
            qDebug() << "foo: " << i;
        }
        void bar(int i) {
            qDebug() << "bar: " << i;
        }
};

这是构造 C 的输出:

B::doit       // this is /* 1 */
foo:  2 
bar:  2 
A::doit       // this is /* 2 */
bar:  1 

... 仅此而已。 Aemit foo(1) 没有连接到 Cfoo 插槽,它永远不会到达CAemit bar(1) 按预期工作,该信号未受影响。

使用该设置,您可以在类准备就绪时发出 newConnectionQTcpServer 版本的信号将不会被您的用户对象接收。

关于c++ - 子类化 QTcpServer 时,如何延迟发出 newConnection() 信号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14143730/

相关文章:

c++ - 无法分配列表迭代器 [C++]

c++ - 第一次填充 QTableWidget 时,一切都很好,但是当我重新填充它时,速度明显变慢

c++ - cURL CURLOPT_WRITEFUNCTION 是否从同一线程调用?

c++ - 如何获取工作站所属的 Active Directory 域的全名

c++ - QVector::replace() 是否创建深拷贝?

.net - .NET 框架中的传输层安全性

javascript - 使用浏览器的证书(私钥)在javascript中签署一些字符串

python - SSL 错误 TLSV1_ALERT_INTERNAL_ERROR 与 aiohttp 库

c++ - 如何将 8 字节数组中的信息传递到可变位大小的数据容器中?

linux - Qt - 设置自定义波特率