SSL 服务器和客户端

使用 QSslSockets 建立安全的远程对象网络

当你需要通过你无法完全控制的网络传递数据时,加密通信是至关重要的。本示例中的两个应用程序展示了如何通过 SSL 连接共享远程对象,以及如何访问它们。

sslserversslcppclient都使用自定义的根 CA 证书来验证对方的证书,这些证书都位于 sslserver/cert 中。

SSL 服务器

SSL 服务器配置了证书和私钥。

自动配置=QSslConfiguration::defaultConfiguration(); config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem"));QFilecertificateFile(QStringLiteral(":/sslcert/server.crt"));if(certificateFile.open(QIODevice::只读|QIODevice::Text)) config.setLocalCertificate(QSslCertificate(certificateFile.readAll() QSsl::Pem));else    qFatal("Could not open certificate file");
QFilekeyFile(QStringLiteral(":/sslcert/server.key"));if(keyFile.open(QIODevice::ReadOnly|QIODevice::Text)) { QSslKeykey(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 端口监听。然后使用QSslServer 对象的 URL 在QRemoteObjectHost 对象上调用 setHostUrl。

QRemoteObjectHost host;
QSslServer server;
server.listen(QHostAddress::Any, 65511);
host.setHostUrl(server.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);

使用 lambda 处理 errorOccurred 信号,将错误输出到终端。第二个 lambda 连接到 pendingConnectionAvailable 信号,该信号连接到错误处理程序,并在QRemoteObjectHost 对象上调用 addHostSideConnection,将输入的套接字作为参数,使主机对象使用套接字进行通信。

QObject连接(&server, &QSslServer::errorOccurred, [](QSslSocket*socket QAbstractSocket::SocketError error) {                     Q_UNUSED(socket);
                     qDebug() << "QSslServer::errorOccurred" << error;
                 });QObject连接(&server, &hostQSslServer::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 对象,并以 MinuteTimer 对象为参数在QRemoteObjectHost 对象上调用 enableRemoting,使其能够共享。

MinuteTimer timer;
host.enableRemoting(&timer);

SSL 客户端

sslcppclient设置根 CA 证书,然后创建一个测试器对象。

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();
}

在测试器构造函数中,会创建一个临时QRemoteObjectNode 对象,并使用 setupConnection 创建和配置QSslSocket 对象。连接错误处理程序,并通过调用 addClientSideConnection 将QSslSocket 用于QRemoteObjectNode 对象。

QRemoteObjectNodem_client;autosocket=setupConnection(); connect(socket, &QSslSocket::errorOccurredsocket [](QAbstractSocket::SocketError error){    qDebug() << "QSslSocket::error" << error;
}) ; m_client.addClientSideConnection(socket);

然后,通过在QRemoteObjectNode 对象上使用 acquire,将作为 Tester 类成员的三个QScopedPointer 连接到 MinuteTimer 的三个副本。最后,QTimer::singleShot 被使用四次,以在延迟后调用重置。

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 时,会检查一个指针是否绑定,然后重置,每次重置的指针都不同。第四次调用时,应用程序将退出。

voidclear() {static inti= 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(); } }

示例项目 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.