Qt / C ++ MQTT / SSL套接字重新连接失败

时间:2020-07-21 09:25:24

标签: linux qt c++11 ssl mqtt

我使用ssl套接字实现了mqtt客户端的传输。问题在于,当断开网络连接并重新连接ssl套接字时,它确实拒绝重新连接。

我创建了一个使用Qt 5.12.3(以及网络和mqtt模块)的实现的最小示例:

#include <QCoreApplication>
#include <QTimer>
#include <QtNetwork/QSslSocket>
#include <QtMqtt/QMqttClient>
#include <QCommandLineParser>
#include <QTimer>
#include <QFileInfo>
#include <QDebug>
#include <QObject>

static QMqttClient* mqtt_client;
static QSslSocket* ssl_socket;
static bool ping_response_received = false;
static QString url = "";

void onSSLEncrypted(){
    qDebug() << "SSL Socket encryption started!";
    if(mqtt_client->state() == QMqttClient::Connected)
    {
        mqtt_client->disconnectFromHost();
    }
    mqtt_client->connectToHostEncrypted();
}

void onCheckPingResponse(){
    if (!ping_response_received)
    {
        qDebug() << "Mqtt client ping timed out";

        if(ssl_socket->state() != QAbstractSocket::ConnectedState && ssl_socket->state() != QAbstractSocket::ConnectingState)
        {
            qDebug() << "Socket is disconnect, trying to reconnect ...";
            ssl_socket->disconnectFromHost();
            ssl_socket->abort();
            ssl_socket->close();
            ssl_socket->connectToHostEncrypted(url, 8333);
            if(!ssl_socket->waitForEncrypted(3000)){
                qDebug() << "ERROR SSL SOCKET!! " << QString::number(ssl_socket->error());
            }
        }
    }

}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QCommandLineParser parser;
    parser.addHelpOption();
    parser.addPositionalArgument("cacert", QCoreApplication::translate("main", "path to ca-cert"));
    parser.addPositionalArgument("certpem", QCoreApplication::translate("main", "path to certpem"));
    parser.addPositionalArgument("privatekey", QCoreApplication::translate("main", "path to privatekey"));
    parser.addPositionalArgument("clientid", QCoreApplication::translate("main", "clientid associated with certificates"));
    parser.addPositionalArgument("url", QCoreApplication::translate("main", "mqtt broker url"));

    parser.process(a);
    const QStringList args = parser.positionalArguments();

    url = args.at(4);
    mqtt_client = new QMqttClient(&a);
    ssl_socket = new QSslSocket(&a);

    QFileInfo ca_cert(args.at(0));
    QFileInfo device_cert(args.at(1));
    QFileInfo private_key(args.at(2));

    ssl_socket->setLocalCertificate(device_cert.filePath(), QSsl::EncodingFormat::Pem);
    ssl_socket->addCaCertificates(ca_cert.filePath(), QSsl::Pem,  QRegExp::FixedString);
    ssl_socket->setPrivateKey(private_key.filePath(), QSsl::Rsa, QSsl::EncodingFormat::Pem);
    ssl_socket->setProtocol(QSsl::SslProtocol::TlsV1_2);

    QObject::connect(ssl_socket, &QSslSocket::encrypted, &onSSLEncrypted);

    QObject::connect(ssl_socket, &QSslSocket::connected, [=](){
        qDebug() << "SSL Socket connected!";
        //ssl_socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
    });

    QObject::connect(ssl_socket, &QSslSocket::disconnected, [=](){
        qDebug() << "SSL Socket disconnected!";
    });



    mqtt_client->setHostname(url);
    mqtt_client->setPort(8883);
    mqtt_client->setClientId(args.at(3));
    mqtt_client->setKeepAlive(20);
    mqtt_client->setTransport(ssl_socket,  QMqttClient::TransportType::SecureSocket);
    mqtt_client->setProtocolVersion(QMqttClient::ProtocolVersion::MQTT_3_1_1);

    QObject::connect(mqtt_client, &QMqttClient::stateChanged, [=](QMqttClient::ClientState state){
        qDebug() << "MQTT Client state changed! " << QString::number(state);
    });

    QObject::connect(mqtt_client, &QMqttClient::errorChanged, [=](QMqttClient::ClientError error){
        qDebug() << "MQTT Client error changed! " << QString::number(error);
    });

    QObject::connect(mqtt_client, &QMqttClient::connected, [=](){
        qDebug() << "MQTT client connected to broker now";
    });

    QObject::connect(mqtt_client, &QMqttClient::disconnected, [=](){
        qDebug() << "MQTT client disconnected from broker";
    });

    QObject::connect(mqtt_client, &QMqttClient::pingResponseReceived, [=](){
        ping_response_received = true;
        qDebug() << "################################### ping response received";
    });

    QTimer* keepalive_timer = new QTimer(&a);
    keepalive_timer->setInterval(20000);
    QObject::connect(keepalive_timer, &QTimer::timeout, [=](){
        qDebug() << "Sending ping request";
        ping_response_received = false;
        mqtt_client->requestPing();
        QTimer::singleShot(5000, &onCheckPingResponse);
    });
    keepalive_timer->start();

    qDebug() << "Connecting to " << url << " on port 8333 as " << args.at(3);

    ssl_socket->connectToHostEncrypted(args.at(4), 8883);
    if(!ssl_socket->waitForEncrypted(5000)){
        qWarning() << "Error waiting for socket encryption";
    }

    return a.exec();
}

您可以克隆存储库并从here

进行构建

该工具的使用方式类似于(连接端口是硬编码的):

Usage: ./mqttreconnect [options] cacert certpem privatekey clientid url

Options:
  -h, --help  Displays this help.

Arguments:
  cacert      path to ca-cert
  certpem     path to certpem
  privatekey  path to privatekey
  clientid    clientid associated with certificates
  url         mqtt broker url

当我运行程序时

$ ./mqttreconnect ca-cert.pem cert.pem private.key my-client URL.iot.eu-central-1.amazonaws.com    
Connecting to "URL.iot.eu-central-1.amazonaws.com"  on port 8333 as  "my-client"
SSL Socket connected!
SSL Socket encryption started!
MQTT Client state changed!  "1"
MQTT Client state changed!  "2"
MQTT client connected to broker now
Sending ping request
################################### ping response received
################################### ping response received //Here I disconnected internet access
Sending ping request
Mqtt client ping timed out
Sending ping request
Mqtt client ping timed out
Sending ping request //Here I reconnected internet access
"Socket is disconnect, trying to reconnect ..."
MQTT Client state changed!  "0"
MQTT client disconnected from broker
MQTT Client error changed!  "256"
ERROR SSL SOCKET!!  "1"
Sending ping request
Mqtt client ping timed out
"Socket is disconnect, trying to reconnect ..."
ERROR SSL SOCKET!!  "1"
Sending ping request
Mqtt client ping timed out
"Socket is disconnect, trying to reconnect ..."
ERROR SSL SOCKET!!  "1"
Sending ping request
Mqtt client ping timed out
"Socket is disconnect, trying to reconnect ..."
ERROR SSL SOCKET!!  "1"
Sending ping request
Mqtt client ping timed out
"Socket is disconnect, trying to reconnect ..."
ERROR SSL SOCKET!!  "1"

QAbstractSocket::RemoteHostClosedError等同于此错误1,但没有任何意义-尝试重新连接套接字时,我中止了所有连接,将其关闭并尝试重新连接。

为什么这不起作用?

0 个答案:

没有答案