SSLサーバーとクライアント
QSslSocketsを使用したセキュアなリモート・オブジェクト・ネットワークのセットアップ。
通信を暗号化することは、完全に制御できないネットワークを通してデータを渡す必要がある場合に重要です。この例の2つのアプリケーションは、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 オブジェクトにQSslServer オブジェクトの URL を指定して setHostUrl を呼び出す。
QRemoteObjectHost host; QSslServer server; server.listen(QHostAddress::Any, 65511); host.setHostUrl(server.serverAddress().toString(), QRemoteObjectHost::AllowExternalRegistration);
errorOccurredシグナルを処理するためにラムダが使用され、エラーがターミナルに出力される。2番目のラムダは、エラーハンドラを接続する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 オブジェクト上でMinuteTimerオブジェクトを引数として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 オブジェクトを作成し設定します。エラー・ハンドラが接続され、QSslSocket に addClientSideConnection を呼び出すことで、QRemoteObjectNode オブジェクトが使用される。
QRemoteObjectNode m_client; auto socket = setupConnection(); connect(socket, &QSslSocket::errorOccurred, socket, [](QAbstractSocket::SocketError error){ qDebug() << "QSslSocket::error" << error; }) ; m_client.addClientSideConnection(socket);
次に、Testerクラスのメンバである3つのQScopedPointer 、QRemoteObjectNode オブジェクトでacquireを使用して、MinuteTimerの3つのレプリカに接続される。最後にQTimer::singleShot 、遅延の後にresetを4回呼び出す。
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が最初の3回呼び出されると、1つのポインタがバインドされていることがチェックされ、毎回異なるポインタがリセットされます。4回目に呼び出されると、アプリケーションが終了します。
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 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 本書で提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。