SSL服务器和客户端
使用QSslSockets设置安全的远程对象网络。
当你需要通过没有完全控制权的网络传递数据时,加密通信是至关重要的。本示例中的两个应用程序展示了如何在SSL连接上共享远程对象以及如何访问它们。
在本示例中,sslserver 和 sslcppclient 均使用自定义的根CA证书来验证对方的证书,所有证书都位于 sslserver/cert 中。
SSL服务器
sslserver 已经配置了证书和私钥。
auto config = QSslConfiguration::defaultConfiguration(); config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem"))); QFile certificateFile(QStringLiteral(":/sslcert/server.crt")); if (certificateFile.open(QIODevice::ReadOnly | QIODevice::Text)) config.setLocalCertificate(QSslCertificate(certificateFile.readAll(), QSsl::Pem)); else qFatal("Could not open certificate file"); QFile keyFile(QStringLiteral(":/sslcert/server.key")); if (keyFile.open(QIODevice::ReadOnly | QIODevice::Text)) { QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); if (key.isNull()) qFatal("Key is not valid"); config.setPrivateKey(key); } else { qFatal("Could not open key file"); } config.setPeerVerifyMode(QSslSocket::VerifyPeer); QSslConfiguration::setDefaultConfiguration(config);
然后它创建了一个 QRemoteObjectHost 对象和一个 QSslServer 对象。该 QSslServer 对象监听65511端口。然后调用 QRemoteObjectHost 对象的 setHostUrl,传递 QSslServer 对象的URL。
QRemoteObjectHost host; QSslServer server; server.listen(QHostAddress::Any, 65511); host.setHostUrl(server.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);
使用lambda处理errorOccurred
信号,将错误输出到终端。另一个lambda连接到pendingConnectionAvailable
信号,该信号连接一个错误处理程序,并在 QRemoteObjectHost 对象上调用 addHostSideConnection,以将传入的套接字作为参数,使主机对象使用该套接字进行通信。
QObject::connect(&server, &QSslServer::errorOccurred, [](QSslSocket *socket, QAbstractSocket::SocketError error) { Q_UNUSED(socket); qDebug() << "QSslServer::errorOccurred" << error; }); QObject::connect(&server, &QSslServer::pendingConnectionAvailable, [&server, &host]() { qDebug() << "New connection available"; QSslSocket *socket = qobject_cast<QSslSocket *>(server.nextPendingConnection()); Q_ASSERT(socket); QObject::connect(socket, &QSslSocket::errorOccurred, [](QAbstractSocket::SocketError error) { qDebug() << "QSslSocket::error" << error; }); host.addHostSideConnection(socket); });
最后,创建一个 MinuteTimer
对象,并在 QRemoteObjectHost 对象上调用 enableRemoting,该对象作为参数传递,以启用其共享。
MinuteTimer timer; host.enableRemoting(&timer);
SSL客户端
在 sslcppclient 中设置根CA证书,然后创建一个 Tester 对象。
int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); auto config = QSslConfiguration::defaultConfiguration(); config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem"))); QSslConfiguration::setDefaultConfiguration(config); Tester t; return a.exec(); }
在 Tester 构造函数中,创建了一个临时的 QRemoteObjectNode 对象,并使用 setupConnection 创建并配置了一个 QSslSocket 对象。连接了一个错误处理程序,并通过调用 addClientSideConnection 在 QRemoteObjectNode 对象上使用 QSslSocket 对象。
QRemoteObjectNode m_client; auto socket = setupConnection(); connect(socket, &QSslSocket::errorOccurred, socket, [](QAbstractSocket::SocketError error){ qDebug() << "QSslSocket::error" << error; }) ; m_client.addClientSideConnection(socket);
然后,使用 QRemoteObjectNode 对象的 acquire,将通过连接将三个 MinuteTimer 的副本来与其 Tester 类的三个成员 QScopedPointer 连接。最后使用际QTimer::singleShot
四次调用 reset 延时。
ptr1.reset(m_client.acquire< MinuteTimerReplica >()); ptr2.reset(m_client.acquire< MinuteTimerReplica >()); ptr3.reset(m_client.acquire< MinuteTimerReplica >()); QTimer::singleShot(0, this, &Tester::clear); QTimer::singleShot(1, this, &Tester::clear); QTimer::singleShot(10000, this, &Tester::clear); QTimer::singleShot(11000, this, &Tester::clear);
当对于第一次调用 Tester::clear 时,检查一个指针是否已绑定然后重置,每次使用不同的指针。当第四次调用时,将导致应用程序退出。
void clear() { static int i = 0; if (i == 0) { i++; if (ptr1.isNull()) qCritical() << "Pointer 1 was not set"; ptr1.reset(); } else if (i == 1) { i++; if (ptr2.isNull()) qCritical() << "Pointer 2 was not set"; ptr2.reset(); } else if (i == 2) { i++; if (ptr3.isNull()) qCritical() << "Pointer 3 was not set"; ptr3.reset(); } else { qApp->quit(); } }
© 2024 Qt 公司有限公司。本文件中包含的文档贡献均为各自所有者的版权。本文件提供的文档根据免费软件基金会发布的GNU 自由文档许可证(版本 1.3)的条款进行许可。Qt及其相关标志是芬兰 及/或其他国家的Qt 公司有限公司的商标。所有其他商标均属于各自所有者。