当子类化QTcpServer时,我如何延迟发出newConnection()信号?
When subclassing QTcpServer, how can I delay emitting the newConnection() signal?
我想创建一个SSL服务器,所以我子类QTcpServer并覆盖incomingConnection()
,在那里我创建一个QSslSocket
,设置其描述符,并调用QSslSocket::startServerEncryption
。此时,我需要等待QSslSocket::encrypted()
信号发出,只有在此之后,我的服务器才应该发出newConnection()
信号。客户端代码会认为它使用的是QTcpSocket,但实际上它使用的是一个安全套接字。
但是QTcpServer在调用incomingConnection()
后总是发出 newConnection()
(我查看了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
类是QTcpServer
, foo
是你试图"劫持"的信号,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);
};
类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
…没有别的了。A
的emit foo(1)
没有连接到C
的foo
插槽,它永远不会到达C
。A
的emit bar(1)
工作正常,信号未动
有了这样的设置,当你的类准备好时,你可以发出newConnection
, QTcpServer
版本的信号将不会被你的用户对象接收。
要真正减少替换,您可能需要编辑Qt的实际源代码,因为您通常无法重新实现任何Private
类调用。
如果你是唯一一个使用替换的,并且你控制连接到newConnection
信号的类…
只需将newConnection
连接到您自己的插槽handleNewConnection
。当安全连接准备好时,发出myNewConnection
并将其连接到将连接到newConnection
的元素。
编辑:经过一番挖掘,我找到了一个重新连接信号的选项:
http://qt-project.org/forums/viewthread/6820基本上,你重新实现QObject::connect
,然后你跟踪连接并以你需要的方式处理它们。因此,在这种情况下,您将保留newConnection
信号的所有连接的列表,并将其保存在列表中,以便在断开它时可以重新连接它。请确保在重新实现结束时调用QObject::connect
。
当走这条路时,另一个选择是去那里重新路由连接。当从newConnection
请求连接时,将其移到myNewConnection
。
希望对你有帮助。
一个肮脏的黑客将非常短暂地阻止来自QTcpServer的信号。因为您知道newConnection()
将在您从SslServer::incomingConnection()
返回之后立即发出,所以在您返回之前调用this->blockSignals(true);
。这将阻止newConnection()
调用它所连接的任何插槽。
为了确保您接收到后续信号,请尽快解除阻塞信号。我想最早可用的时间将是正确的,当控制回到事件循环,所以QTimer::singleShot可以做到这一点。
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);
}
这样做的缺点是,您将失去在incomingConnection()
和unblockSignals()
之间可以合法发射的所有信号。就像我说的,这是一个肮脏的黑客。
- Qt VTK交互风格的信号到小部件
- 获取日期异步信号安全吗?如果在信号处理程序中使用,它会导致死锁吗
- 如何仅为一个函数添加延迟
- 如何将点击的信号和插槽添加到qt中的自定义按钮中
- 如何在没有信号的情况下从C++执行QML插槽
- 线程之间的布尔停止信号
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- 当用户在qtablewidget中输入单元格时,如何获得信号?C++
- 以在Qt中的IF语句中设置时间延迟
- 有可能在信号处理程序中设置promise吗
- 代码在我的计算机上运行良好,但是在将其提交给coursera时遇到未知的信号11问题
- 在条件变量中触发错误信号的频率是多少
- 模板化类中静态成员的延迟初始化
- 在 Windows 8/10 技术中完全实时的屏幕捕获,没有延迟
- 在信号处理程序中捕获C++未处理的异常并恢复应用程序
- 调试和自由执行中的信号处理
- 在Qt中,如何延迟成员函数的返回,直到收到信号?
- Qt信号以明显的延迟到达UI线程
- Qt QNetworkAccessManager长延迟发出完成信号
- 当子类化QTcpServer时,我如何延迟发出newConnection()信号?