En esta página

Servidor y cliente SSL

Configuración de una red segura de Objetos Remotos usando QSslSockets.

Encriptar la comunicación es crítico cuando necesitas pasar datos a través de una red sobre la que no tienes control total. Las dos aplicaciones de este ejemplo muestran cómo compartir objetos remotos a través de una conexión SSL, y cómo acceder a ellos.

Terminal ejecutando sslserver y mostrando la hora actual

Tanto sslserver como sslcppclient utilizan un certificado CA raíz personalizado para validar los certificados del otro, todos ubicados en sslserver/cert.

Servidor SSL

El sslserver está configurado con certificados y una clave privada.

auto config = QSslConfiguration::defaultConfiguration(); config.setCaCertificates(QSslCertificate::fromPath(QStringLiteral(":/sslcert/rootCA.pem"));QFile certificateFile(QStringLiteral(":/sslcert/servidor.crt"));if (certificateFile.open(QIODevice::Sólo lectura | 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::Texto)) { 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);

Luego crea un objeto QRemoteObjectHost y un objeto QSslServer. El objeto QSslServer escucha en el puerto 65511. Luego se llama a setHostUrl en el objeto QRemoteObjectHost con la URL del objeto QSslServer.

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

Se utiliza un lambda para manejar la señal errorOccurred emitiendo el error al terminal. Un segundo lambda se conecta a la señal pendingConnectionAvailable, que conecta un manejador de errores, y llama a addHostSideConnection en el objeto QRemoteObjectHost con el socket entrante como argumento para hacer que el objeto host use el socket para la comunicación.

QObject::connect(&servidor, &QSslServer::errorOcurrido, [](QSslSocket*socket, QAbstractSocket::SocketError error) {                     Q_UNUSED(socket);
                     qDebug() << "QSslServer::errorOccurred" << error;
                 });QObject::connect(&servidor, &QSslServer::pendingConnectionAvailable, [&servidor, &host]() {    qDebug() << "New connection available";
    QSslSocket *socket =  qobject_cast<QSslSocket *>(server.nextPendingConnection()); Q_ASSERT(socket);    QObject::connect(socket, &QSslSocket::errorOcurrido, [](QAbstractSocket::SocketError error) {                         qDebug() << "QSslSocket::error" << error;
                     }); host.addHostSideConnection(socket); });

Finalmente, se crea un objeto MinuteTimer y se llama a enableRemoting en el objeto QRemoteObjectHost con el objeto MinuteTimer como argumento para permitir que sea compartido.

MinuteTimer timer;
host.enableRemoting(&timer);

Cliente SSL

El sslcppclient establece el certificado CA raíz y luego crea un objeto 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();
}

En el constructor Tester se crea un objeto QRemoteObjectNode temporal, y setupConnection se utiliza para crear y configurar un objeto QSslSocket. Se conecta un manejador de errores, y el QSslSocket es utilizado por el objeto QRemoteObjectNode llamando a addClientSideConnection en él.

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

Luego tres QScopedPointer que son miembros de la clase Tester son conectados a tres réplicas de MinuteTimer usando acquire en el objeto QRemoteObjectNode. Finalmente QTimer::singleShot se utiliza cuatro veces para llamar a reset después de un retardo.

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

Cuando se llama a Tester::clear las tres primeras veces, se comprueba que un puntero está enlazado y luego se reinicia, para un puntero diferente cada vez. Cuando se llama por cuarta vez se provoca el abandono de la aplicación.

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

Proyecto de ejemplo @ code.qt.io

© 2026 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.