Bootstrap

通过Qt的QSslSocket和QNetworkAccessManager访问https

1. main.cpp

#include <QCoreApplication>
#include <QSslSocket>
#include <QSslCertificate>
#include <QtNetwork>
#include "outsocket.h"
#include "replyhandler.h"
#include <QNetworkAccessManager>


//1. Visit "https://blog.csdn.net" by QNetworkAccessManager::get
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);


    QNetworkAccessManager mgr;
    QNetworkRequest request(QUrl("https://blog.csdn.net"));
    QNetworkReply *reply = mgr.get(request);
    ReplyHandler handler(reply);

    bool b1  = QObject::connect(reply, SIGNAL(downloadProgress(qint64, qint64 )                                  ), &handler, SLOT(slt_downloadProgress(qint64, qint64 )));
    bool b2  = QObject::connect(reply, SIGNAL(encrypted()                                                        ), &handler, SLOT(slt_encrypted()));
    bool b3  = QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError )                                ), &handler, SLOT(slt_error(QNetworkReply::NetworkError )));
    bool b4  = QObject::connect(reply, SIGNAL(finished()                                                         ), &handler, SLOT(slt_finished()));
    bool b5  = QObject::connect(reply, SIGNAL(metaDataChanged()                                                  ), &handler, SLOT(slt_metaDataChanged()));
    bool b6  = QObject::connect(reply, SIGNAL(preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *)), &handler, SLOT(slt_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *)));
    bool b7  = QObject::connect(reply, SIGNAL(redirectAllowed()                                                  ), &handler, SLOT(slt_redirectAllowed()));
    bool b8  = QObject::connect(reply, SIGNAL(redirected(const QUrl &)                                           ), &handler, SLOT(slt_redirected(const QUrl &)));
    bool b9  = QObject::connect(reply, SIGNAL(sslErrors(const QList<QSslError> &)                                ), &handler, SLOT(slt_sslErrors(const QList<QSslError> &)));
    bool b10 = QObject::connect(reply, SIGNAL(uploadProgress(qint64 , qint64 )                                   ), &handler, SLOT(slt_uploadProgress(qint64 , qint64 )));
    bool b11= QObject::connect(reply, SIGNAL(aboutToClose()                                                     ), &handler, SLOT(slt_aboutToClose()));
    bool b12 = QObject::connect(reply, SIGNAL(bytesWritten(qint64 )                                              ), &handler, SLOT(slt_bytesWritten(qint64 )));
    bool b13 = QObject::connect(reply, SIGNAL(channelBytesWritten(int , qint64 )                                 ), &handler, SLOT(slt_channelBytesWritten(int , qint64 )));
    bool b14 = QObject::connect(reply, SIGNAL(channelReadyRead(int )                                             ), &handler, SLOT(slt_channelReadyRead(int )));
    bool b15 = QObject::connect(reply, SIGNAL(readChannelFinished()                                              ), &handler, SLOT(slt_readChannelFinished()));
    bool b16 = QObject::connect(reply, SIGNAL(readyRead()                                                        ), &handler, SLOT(slt_readyRead()));

    qDebug() << b1
             << b2
             << b3
             << b4
             << b5
             << b6
             << b7
             << b8;

    qDebug() << b9
             << b10
             << b11
             << b12
             << b13
             << b14
             << b15
             << b16;


    reply->ignoreSslErrors();
    return a.exec();
}


//2. Visit "https://www.baidu.com" by QSslSocket
int main1(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    OutSocket *out = new OutSocket();
    QSslSocket socket;
    bool ok1 = QObject::connect(&socket, &QSslSocket::modeChanged,      out, &OutSocket::slt_modeChanged);
    bool ok2 = QObject::connect(&socket, &QSslSocket::peerVerifyError,  out, &OutSocket::slt_peerVerifyError);
    bool ok3 = QObject::connect(&socket, SIGNAL(sslErrors(const QList<QSslError> &)),        out, SLOT(slt_sslErrors(const QList<QSslError> &)));
    bool ok4 = QObject::connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)),        out, SLOT(slt_error(QAbstractSocket::SocketError)));
    bool ok5 = QObject::connect(&socket, &QSslSocket::hostFound,        out, &OutSocket::slt_hostFound);
    bool ok6 = QObject::connect(&socket, &QSslSocket::stateChanged,     out, &OutSocket::slt_stateChanged);
    qDebug() << ok1 << ok2 << ok3 << ok4 << ok5 << ok6;

    //socket.ignoreSslErrors();
    socket.connectToHostEncrypted("www.baidu.com", 443);
    if (!socket.waitForEncrypted())
    {
        qDebug() << "errorString:" << socket.errorString();
        return -1;
    }
    qDebug() << "connected!\n";
    qDebug() << "sslErrors" << socket.sslErrors();

    qDebug() << "sslLibraryVersionNumber" << socket.sslLibraryVersionNumber();
    qDebug() << "sslLibraryVersionString" << socket.sslLibraryVersionString();
    qDebug() << "sslLibraryBuildVersionNumber" << socket.sslLibraryBuildVersionNumber();
    qDebug() << "sslLibraryBuildVersionString" << socket.sslLibraryBuildVersionString();
    qDebug() << "caCertificates" << socket.sslConfiguration().caCertificates();
    qDebug() << "localCertificate" << socket.sslConfiguration().localCertificate().toText();
    qDebug() << "peerCertificate" << socket.sslConfiguration().peerCertificate().toText();

    socket.write("GET / HTTP/1.0\r\n\r\n");
     while (socket.waitForReadyRead())
         qDebug() << socket.readAll().data();

    socket.close();
    qApp->exit();
    return a.exec();
}

2.outsocket.h

#ifndef OUTSOCKET_H
#define OUTSOCKET_H

#include <QObject>
#include <QtNetwork>


class OutSocket : public QObject
{
    Q_OBJECT
public:
    explicit OutSocket(QObject *parent = nullptr) : QObject(parent)
    {

    }
    virtual ~OutSocket()
    {

    }

public slots:
    void	slt_modeChanged ( QSslSocket::SslMode mode )
    {
        qDebug() << "slt_modeChanged" << mode;
    }

    void	slt_peerVerifyError ( const QSslError & error )
    {
        qDebug() << "slt_peerVerifyError" << error;
    }

    void	slt_sslErrors ( const QList<QSslError> & errors )
    {
        qDebug() << "slt_sslErrors" << errors;
    }


    void	slt_error ( QAbstractSocket::SocketError socketError )
    {
        qDebug() << "slt_error" << socketError;
    }

    void	slt_hostFound ()
    {
        qDebug() << "slt_hostFound";
    }

    void	slt_stateChanged ( QAbstractSocket::SocketState socketState )
    {
        qDebug() << "slt_stateChanged" << socketState;
    }

};


#endif // OUTSOCKET_H
#ifndef REPLYHANDLER_H
#define REPLYHANDLER_H

#include <QNetworkReply>
#include <QObject>

class ReplyHandler : public QObject
{
    Q_OBJECT
public:
    explicit ReplyHandler(QNetworkReply *repy, QObject *parent = nullptr) :
        QObject(parent),
        _reply(repy)
    {

    }

public slots:
    void slt_downloadProgress(qint64 bytesReceived, qint64 bytesTotal)
    {
        qDebug() << "slt_downloadProgress" << bytesReceived << bytesTotal;
    }
    void slt_encrypted()
    {
        qDebug() << "slt_encrypted";
    }
    void slt_error(QNetworkReply::NetworkError code)
    {
        qDebug() << "slt_error" << code;
    }
    void slt_finished()
    {
        qDebug() << "slt_finished";
    }
    void slt_metaDataChanged()
    {
        qDebug() << "slt_metaDataChanged";
    }
    void slt_preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator)
    {
        qDebug() << "slt_preSharedKeyAuthenticationRequired" << authenticator;
    }
    void slt_redirectAllowed()
    {
        qDebug() << "slt_redirectAllowed";
    }
    void slt_redirected(const QUrl &url)
    {
        qDebug() << "slt_redirected" << url;
    }
    void slt_sslErrors(const QList<QSslError> &errors)
    {
        qDebug() << "slt_sslErrors" << errors;
    }
    void slt_uploadProgress(qint64 bytesSent, qint64 bytesTotal)
    {
         qDebug() << "slt_uploadProgress" << bytesSent << bytesTotal;
    }
    void slt_aboutToClose()
    {
        qDebug() << "slt_aboutToClose";
    }
    void slt_bytesWritten(qint64 bytes)
    {
        qDebug() << "slt_bytesWritten" << bytes;
    }
    void slt_channelBytesWritten(int channel, qint64 bytes)
    {
        qDebug() << "slt_channelBytesWritten" << channel << bytes;
    }
    void slt_channelReadyRead(int channel)
    {
        qDebug() << "slt_channelReadyRead" << channel;
    }
    void slt_readChannelFinished()
    {
        qDebug() << "slt_readChannelFinished";
    }
    void slt_readyRead()
    {
        qDebug() << "slt_readyRead";
        while (_reply->bytesAvailable())
        {
            qDebug() << "readAll:" << QString(_reply->readAll());
        }
    }


private:
    QNetworkReply *_reply;
};

#endif // REPLYHANDLER_H

4.环境

Windows 7 + Desktop Qt 5.9.9 MinGW 32bit

5.相关错误解决

类似以下错误,是因为缺少库(libeay32.dll,ssleay32.dll),电脑上很多软件(迅雷、微信)都带有(everything软件搜索),查看dll属性找版本号新的,放入到软件运行路径下即可。

qt.network.ssl: QSslSocket: cannot call unresolved function XXX
QSslSocket:无法解析TLSv1_1_client_method
QSslSocket:无法解析TLSv1_2_client_method

----------------------------------------------

;