Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在子类化QTcpServer时,如何延迟发出newConnection()信号?_C++_Qt_Ssl_Qtcpserver_Qt Signals - Fatal编程技术网

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

C++ 在子类化QTcpServer时,如何延迟发出newConnection()信号?,c++,qt,ssl,qtcpserver,qt-signals,C++,Qt,Ssl,Qtcpserver,Qt Signals,我想创建一个SSL服务器,所以我将qtcserver作为子类,并重写incomingConnection(),在这里我创建一个QSslSocket,设置它的描述符,然后调用qsslssocket::startServerEncryption。此时,我需要等待发出qsslssocket::encrypted()信号,然后我的服务器才会发出newConnection()信号。然后,客户端代码会认为它使用的是QTcpSocket,但实际上使用的是安全套接字 但是qtcserver在调用incoming

我想创建一个SSL服务器,所以我将qtcserver作为子类,并重写
incomingConnection()
,在这里我创建一个
QSslSocket
,设置它的描述符,然后调用
qsslssocket::startServerEncryption
。此时,我需要等待发出
qsslssocket::encrypted()
信号,然后我的服务器才会发出
newConnection()
信号。然后,客户端代码会认为它使用的是QTcpSocket,但实际上使用的是安全套接字

但是qtcserver在调用
incomingConnection()
之后总是发出
newConnection()
(我查看了一下):

我的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;
    }
}

要成为真正的替代品,您可能需要编辑Qt的实际源代码,因为您通常无法重新实现任何
Private
class调用

如果您是唯一使用替换连接的用户,并且您控制连接到
newConnection
信号的类

只需将
newConnection
连接到您自己的插槽
handleNewConnection
。当安全连接准备就绪时,发出
myNewConnection
,并将其连接到本应连接到
newConnection
的元素

编辑: 经过一番挖掘,我找到了重新连接信号的选项:

基本上,您需要重新实现
QObject::connect
,然后跟踪连接并按需要的方式处理它们。因此,在本例中,您将保留信号
newConnection
的所有连接的列表,并将其保存在列表中,以便在断开连接时可以重新连接。确保在重新实现结束时调用
QObject::connect

走这条路线时的另一个选择是,去那里重新路由连接。当从
newConnection
请求连接时,将其移动到
myNewConnection


希望这会有所帮助。

要成为真正的替代品,您可能需要编辑Qt的实际源代码,因为您通常无法重新实现任何
私有
类调用

如果您是唯一使用替换连接的用户,并且您控制连接到
newConnection
信号的类

只需将
newConnection
连接到您自己的插槽
handleNewConnection
。当安全连接准备就绪时,发出
myNewConnection
,并将其连接到本应连接到
newConnection
的元素

编辑: 经过一番挖掘,我找到了重新连接信号的选项:

基本上,您需要重新实现
QObject::connect
,然后跟踪连接并按需要的方式处理它们。因此,在本例中,您将保留信号
newConnection
的所有连接的列表,并将其保存在列表中,以便在断开连接时可以重新连接。确保在重新实现结束时调用
QObject::connect

走这条路线时的另一个选择是,去那里重新路由连接。当从
newConnection
请求连接时,将其移动到
myNewConnection


希望这能有所帮助。

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

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

这里有一个概念证明:class
a
qtcserver
foo
是您试图“劫持”的信号,
bar
只是
qtcserver
的另一个(假设)信号,您不需要触摸

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);
};
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;
        }
};
。。。没有别的了<代码>A的
发出foo(1)
未连接到
C的
foo
插槽,它将永远不会到达
C
<代码>一个
发射条(1)按预期工作,该信号未被触及


通过该设置,您可以在类准备就绪时发出
newConnection
,用户对象将不会接收到
qtcserver
版本的信号。

在这种情况下,有一个想法可以奏效:在
qtcserver
子类中重新定义
newConnection
信号

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

这里有一个概念证明:class
a
qtcserver
foo
是您试图“劫持”的信号,
bar
只是
qtcserver
的另一个(假设)信号,您不需要触摸

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);
};
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;
        }
};
。。。没有别的了<代码>A的
发出foo(1)
未连接到
C的
foo
插槽,它将永远不会到达
C
<代码>一个
发射条(1)按预期工作,该信号未被触及


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

一个肮脏的黑客行为是非常短暂地阻止来自qtcserver的信号。因为您知道,
newConnection()
将在您从
SslServer::incomingConnec返回后立即发出
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;
        }
};
B::doit       // this is /* 1 */
foo:  2 
bar:  2 
A::doit       // this is /* 2 */
bar:  1 
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;
    }

    this -> blockSignals(true);
    QTimer::singleShot(0, this, SLOT(unblockSignals());
}

void SslServer::unblockSignals()
{
    this->blockSignals(false);
}