由于QSslSocket的setLocalCertificate而导致Qt控制台应用程序崩溃

时间:2019-04-11 14:03:43

标签: qt ssl

需要创建一个使用SSL连接到客户端的小型服务器应用程序。一次只能连接一个客户端。

客户端每次尝试建立新连接时,都会调用以下功能

void Control::on_newConnection(){

    if (socket != nullptr) return;

    logger.appendStandard("New connection received 0");

    // New connection is available.
    socket = (QSslSocket*)(listener->nextPendingConnection());

    logger.appendStandard("New connection received 1");

    if (!socket->isValid()) {
        logger.appendError("ERROR: Could not cast incomming socket connection");
        return;
    }

    logger.appendStandard("New connection received 2");

    // Doing the connections.
    connect(socket,SIGNAL(encrypted()),this,SLOT(on_encryptedSuccess()));
    connect(socket,SIGNAL(sslErrors(QList<QSslError>)),this,SLOT(on_sslErrors(QList<QSslError>)));
    connect(socket,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,SLOT(on_socketStateChanged(QAbstractSocket::SocketState)));
    connect(socket,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(on_socketError(QAbstractSocket::SocketError)));
    connect(socket,&QSslSocket::readyRead,this,&Control::on_readyRead);
    connect(socket,&QSslSocket::disconnected,this,&Control::on_disconnected);

    logger.appendStandard("New connection received 3");

    // The SSL procedure.
    socket->setPrivateKey(":/certificates/server.key");
    logger.appendStandard("New connection received 3.1");
    socket->setLocalCertificate(":/certificates/server.csr");
    logger.appendStandard("New connection received 3.2");
    socket->setPeerVerifyMode(QSslSocket::VerifyNone);
    logger.appendStandard("New connection received 3.2");
    socket->startServerEncryption();

    logger.appendStandard("New connection received 4");

}

服务器是一个正在运行的应用程序,用于监听连接。建立连接后,我将根据客户端的要求进行处理,然后使用此功能删除连接。

void Control::clearSocket(const QString &fromWhere){
    if (socket != nullptr){
        logger.appendStandard(fromWhere + ": About to delete socket");
        delete socket;
        socket = nullptr;
        logger.appendStandard(fromWhere + ": Socket deleted!");
    }
}

这在客户端第一次发出请求时非常有效。建立连接后,服务器接收请求,客户端接收答案,然后在客户端关闭服务器时删除服务器中的连接。

但是,当我第二次要执行完全相同的事务时,服务器程序在此行崩溃:

    socket->setLocalCertificate(":/certificates/server.csr");

由于日志消息,我知道这一点。

有人知道为什么会这样吗?

1 个答案:

答案 0 :(得分:0)

事件队列中与基于QObject的已删除套接字对象相关的某些事件可能导致崩溃。

要安全删除,请使用socket->deleteLater()而不是直接调用delete。它计划通过事件循环删除该对象,并且该对象的所有未决事件将从事件队列中删除。