суббота, 29 января 2011 г.

Qt. QNetworkAccessManager и http(https)

Qt предоставляет очень мощные средства для работы с сетью.  Одним из основных инструментов является класс QNetworkAccessManager. Он позволяет отправлять запросы на сайты и получать ответы с них. Рассмотрим основные элементы для его реализации:

        Используя протокол http:

QNetworkAccessManager* m_manager;
QNetworkReply* m_reply;
QNetworkRequest m_request;
QUrl m_url;
QByteArray m_options;

QNetworkAccessManager – основное звено.  QNetworkRequest запрос к сайту. Он содержит адресс сайта, а также передаваемые для него параметры. QUrl – адрес сайта, m_options – строка с параметрами запроса. QNetworkReply  -  класс для хранения ответа с сервером.
Далее посылаем запрос на сайт и считываем ответ в m_reply:

m_url = "http://www.yoursite.com/script.php";
m_options = "param1=1&param2=2";
m_request.setUrl(m_url);
m_reply = m_manager->post(m_request, m_options);

connect(m_reply, SIGNAL(finished()), this, SLOT(slotFinished()));
connect(m_reply, SIGNAL(readyRead()), this, SLOT(slotRead()));

В данном случае мы выполняем запрос с помощью метода Post, но также можно посылать запрос с методом Get. Отличие лишь будет в том, что адрес сайта и параметры нужно обьеденить в одну строку:

m_reply = m_manager->post("http://www.yoursite.com/script.php? param1=1&param2=2");


        При обращении к серверу сайта, QNetworkReply сгенерирует 2 сигнала – finished() и readyRead(). Первый говорит о том что все операции завершены, и объект класса QNetworkReply уже не будет изменён(после этого сигнала рекомендуется удалять ответ m_reply: m_reply->deleteLater()), а второй говорит о том, что данные считаны ими можно оперировать. Присоединяем эти сигналы к нашим слотам и производим считывание данных.

QByteArray htmlPage = m_reply->readAll();

Функция readAll()  возвращает результат запроса в виде QByteArray. После этого можно записывать данные в файл, либо оперировать ими в программе.

Используя протокол https:

При использовании протокола https программа не сильно изменяется. В адресе сайта просто вместо http пишется https. Но появляются некоторые трудности.
Первая из них, это игнорирование ssl ошибок при соединении.  Её легко решить так: 

connect(m_reply, SIGNAL(sslErrors(QList<QSslError>)), m_reply, SLOT(ignoreSslErrors()));

А вторая, это отсутствие алгоритмов шифрования в Qt для соединения с сервером. Возникают такие ошибки при соединении:

QSslSocket: cannot call unresolved function SSLv3_client_method
QSslSocket: cannot call unresolved function SSL_CTX_new
QSslSocket: cannot call unresolved function SSL_library_init
QSslSocket: cannot call unresolved function ERR_get_error
QSslSocket: cannot call unresolved function ERR_error_string


Если видите эти строки, вам нужен OpenSsl. Его можно достать на официальном сайте. Я писал на ОС Windows, так что последние версии сборок можно достать здесь .

После подключения OpenSsl к Qt, проблемы больше не возникнут. Программа обратиться к сайту и получит ответ от него. 

5 комментариев:

  1. Спасибо за статью,
    во втором случае посылки запроса с урлом с параметрами вы имели в виду get или всё-таки пост?

    ОтветитьУдалить
  2. если вы про объединение всех параметров в одну строку, то имел ввиду Get

    ОтветитьУдалить
  3. Ваш вариант годится только для единичных запросов. При осуществлении массовых запросов нужно или наследовать от QNetworkReply и в наследнике ловить сигналы, или использовать сигнал QNetworkAccessManager::finished(QNetworkReply*), передающий нужный указатель.

    ОтветитьУдалить
  4. did you have a sample with https? I'm stuck with it

    ОтветитьУдалить
  5. добрый день
    подскажите, пожалуйста, как подключить OpenSsl к Qt?
    это в проекте надо опции сборки указать? какие?

    ОтветитьУдалить