- 1. QNetworkReply::ConnectionRefusedError і QNetworkReply::RemoteHostClosedError
- 2. QNetworkReply::HostNotFoundError
- 3. QNetworkReply::TimeoutError
- 4. QNetworkReply::OperationCanceledError
- 5. QNetworkReply::SslHandshakeFailedError
- 6. QNetworkReply::TemporaryNetworkFailureError і QNetworkReply::NetworkSessionFailedError
- 7. QNetworkReply::BackgroundRequestNotAllowedError
- 8. QNetworkReply::TooManyRedirectsError і QNetworkReply::InsecureRedirectError
- 9. Помилки QNetworkReply::Proxy*
- 10. QNetworkReply::ContentAccessDenied
- 11. QNetworkReply::AuthenticationRequiredError
- 12. QNetworkReply::ContentReSendError
- 13. QNetworkReply::ContentConflictError
- 14. QNetworkReply::ContentGoneError
- 15. QNetworkReply::InternalServerError
- 16. QNetworkReply::OperationNotImplementedError
- 17. QNetworkReply::ProtocolUnknownError
- 18. QNetworkReply::ServiceUnavailableError
- 19. QNetworkReply::ProtocolInvalidOperationError
- 20. QNetworkReply::UnknownNetworkError
- 21. QNetworkReply::UnknownProxyError
- 22. Ошибки QNetworkReply::UnknownContentError,QNetworkReply::ProtocolFailure, QNetworkReply::UnknownServerError
- 23. Приклад з виведенням помилки в qDebug
В одному з уроків було представлено роботу з QNetworkAccessManager для отримання вмісту сторінки з сайту за протоколом http. Там була зроблена перевірка на наявність помилок, але були дані пояснення, які можуть бути помилки. Для цього клас QNetworkReply надає enum NetworkError , у якому перераховані коди можливих помилок.
У разі успішного виконання повертається NoError , рівний 0 .
В іншому випадку повертається код помилки з кодів, наведених нижче:
Постійна | Значення | Опис |
---|---|---|
QNetworkReply::ConnectionRefusedError | 1 | Видалений сервер відхилив з'єднання (сервер не приймає запити) |
QNetworkReply::RemoteHostClosedError | 2 | віддалений сервер закрив з'єднання передчасно, до того, як вся відповідь була отримана та оброблена |
QNetworkReply::HostNotFoundError | 3 | віддалений хост не знайдено (недійсне ім'я хоста) |
QNetworkReply::TimeoutError | 4 | підключення до віддаленого сервера закінчилося |
QNetworkReply::OperationCanceledError | 5 | операцію було скасовано через виклик abort() або close() до завершення. |
QNetworkReply::SslHandshakeFailedError | 6 | Підключення через SSL/TLS не вдалося, шифрований канал не може бути. Повинен випромінювати сигнал sslErrors(). |
QNetworkReply::TemporaryNetworkFailureError | 7 | з'єднання було порушено через відключення від мережі, проте система ініціювала роумінг до іншої точки доступу. Запит повинен бути повторно та буде оброблений, як тільки з'єднання буде відновлено. |
QNetworkReply::NetworkSessionFailedError | 8 | з'єднання було порушено через відключення від мережі або неможливості запуску мережі. |
QNetworkReply::BackgroundRequestNotAllowedError | 9 | запит на даний час не допускається через політику платформи. |
QNetworkReply::TooManyRedirectsError | 10 | кількість редиректів перевищила допустимий ліміт. За промовчанням ліміт встановлено на 50 редиректів через QNetworkRequest::setMaxRedirectsAllowed(). |
QNetworkReply::InsecureRedirectError | 11 | під час обробки редиректів, API доступу по мережі виявило редирект із шифрованого протоколу (https) на не шифрований (http) |
QNetworkReply::ProxyConnectionRefusedError | 101 | у підключенні до проксі-сервера відмовили (проксі-сервер не приймає запити) |
QNetworkReply::ProxyConnectionClosedError | 102 | проксі-сервер закрив з'єднання передчасно, до того, як вся відповідь була отримана та оброблена |
QNetworkReply::ProxyNotFoundError | 103 | проксі-хост не знайдено (недійсне ім'я проксі хоста) |
QNetworkReply::ProxyTimeoutError | 104 | підключення до проксі-сервера закінчилося або проксі-сервер не відповів вчасно на відправлений запит |
QNetworkReply::ProxyAuthenticationRequiredError | 105 | проксі-сервер вимагає аутентифікації для того, щоб задовольнити запит, але не прийняв будь-яких запропонованих облікових даних (якщо є) |
QNetworkReply::ContentAccessDenied | 201 | у доступі до віддаленого контенту відмовлено (за аналогією з помилкою HTTP 401) |
QNetworkReply::ContentOperationNotPermittedError | 202 | Запитана операція на віддалений вміст не допускається |
QNetworkReply::ContentNotFoundError | 203 | віддалений контент не знайдено на сервері (аналогічно помилці HTTP 404) |
QNetworkReply::AuthenticationRequiredError | 204 | віддалений сервер вимагає аутентифікації, щоб надати контент, але надані облікові дані не були прийняті (якщо є) |
QNetworkReply::ContentReSendError | 205 | запит необхідно надіслати повторно, але це не вдалося, наприклад, тому що завантаження даних не може бути прочитане вдруге. |
QNetworkReply::ContentConflictError | 206 | запит не може бути завершено через конфлікт із поточним станом ресурсу. |
QNetworkReply::ContentGoneError | 207 | Запитаний ресурс більше не доступний на сервері. |
QNetworkReply::InternalServerError | 401 | Сервер зіткнувся з непередбаченою умовою, яка дозволяє йому виконати запит. |
QNetworkReply::OperationNotImplementedError | 402 | сервер не підтримує функціональних можливостей, необхідних для виконання запиту. |
QNetworkReply::ServiceUnavailableError | 403 | сервер не може обробити запит на даний момент. |
QNetworkReply::ProtocolUnknownError | 301 | Network Access API неспроможна задовольнити запит, оскільки протокол не відомий |
QNetworkReply::ProtocolInvalidOperationError | 302 | запитана операція неприпустима цього протоколу |
QNetworkReply::UnknownNetworkError | 99 | було виявлено невідому помилку мережі |
QNetworkReply::UnknownProxyError | 199 | було виявлено невідому помилку проксі |
QNetworkReply::UnknownContentError | 299 | було виявлено невідому помилку, пов'язану з віддаленим вмістом |
QNetworkReply::ProtocolFailure | 399 | був виявлений збій у протоколі (помилка синтаксичного аналізу, недійсні чи несподівані відповіді тощо) |
QNetworkReply::UnknownServerError | 499 | було виявлено невідому помилку, пов'язану з відповіддю сервера |
Після вивчення даного списку помилок можна зробити висновок, що цей список поєднує значно більший список помилок, ніж, наприклад, той список кодів помилок, який може повернути http сервер. Давайте поговоримо трохи про можливі помилки і через що вони можуть виникнути.
QNetworkReply::ConnectionRefusedError і QNetworkReply::RemoteHostClosedError
Якщо говорити про інтерпретацію даних помилок, то найбільш яскравим прикладом для мене є підключення SSH до іншого хосту. Сенс помилок у цьому, що у першому випадку сервер нас не пускає, тоді як у другому випадку з'єднання може бути закрито після закінчення певного періоду часу.
Також помилка ConnectionRefusedError може виникати у випадках, коли на певному порту ПК просто немає служби, яка б обробила запит.
QNetworkReply::HostNotFoundError
Мабуть, досить зрозуміла помилка, яка означає, що ви просто ввели невірну ip адресу або домен, з якого намагаєтеся отримати дані. Також, така помилка може виникнути в тому випадку, якщо домен перестав бути доступним у мережі. Ця помилка аналогічна до помилки номер 105 - ERR_NAME_NOT_RESOLVED (HTTP).
QNetworkReply::TimeoutError
Перевищено інтервал очікування. Найбільш близьке порівняння - це використання протоколу ICMP, перевірка доступності вузла в мережі, коли робимо його ping. Тобто вузол у мережі начебто і є, але він не відповідає.
QNetworkReply::OperationCanceledError
А ось помилка, яка буде ставитися вже до дій програми на Qt. В даному випадку вона буде виникати тоді, коли логіка програми перериває отримання даних через QNetworkAccessManager. Тобто дана помилка не повинна виникати в тому випадку, якщо операцію отримання даних було перервано ззовні. Тому якщо Ви відловлюєте подібну помилку, то шукайте проблему всередині вашої власної програми.
QNetworkReply::SslHandshakeFailedError
Для встановлення шифрованих каналів зв'язку, які використовують шифрування SSL, потрібне встановлення з'єднання через операції квитування, тобто через підтвердження прийому/передачі інформації. В даному випадку здійснюється узгодження параметрів шифрування, передача сеансового ключа, а також необов'язкові операції автентифікації сервера клієнта та сервера. Якщо щось із перерахованого піде не так, то буде викинуто цю помилку.
QNetworkReply::TemporaryNetworkFailureError і QNetworkReply::NetworkSessionFailedError
Виникнення цих помилок може бути викликано будь-якою неполадкою в мережі, аж до падіння фізичного підключення до мережі. Перевірити підключення можна через клас QNetworkInterface.
Клас
QNetworkInterface
має статичний метод
QList
Тому, щоб зрозуміти, що не так, при отриманні помилок QNetworkReply::TemporaryNetworkFailureErro r та QNetworkReply::NetworkSessionFailedError доведеться протестувати інтерфейси ПК на предмет активності: QNetworkInterface::IsUp та ::IsRunning.
QNetworkReply::BackgroundRequestNotAllowedError
А ось ця помилка залежить безпосередньо від політик платформи, для якої розробляється програма. Наприклад, якщо під деяким абстрактним Android пристроєм заборонено обмін інформацією по мережі в енергозберігаючому режимі, то в даному режимі ми отримуватимемо саме цю помилку, при спробі обміну інформацією.
QNetworkReply::TooManyRedirectsError і QNetworkReply::InsecureRedirectError
А ось ці помилки з розряду нового в Qt 5.6. Тепер можна відслідковувати перевищення кількості редиректів зі сторінок сайтів, а також редиректи зі сторінок із шифруванням https на сторінки без шифрування. Що може бути корисним для розробки програмного забезпечення для аналізу сайтів.
Без додаткових налаштувань дані помилки зазвичай не виникають. Справа в тому, що коли задається QNetworkRequest і в нього не встановлюються прапори конфігурації, то при спробі запиту сторінки із сайту, з якої здійснюється редирект, не відбуватиметься переходу на новий url, а в QNetworkReply не буде жодного корисного контенту. Тому потрібно встановити в QNetworkRequest прапорець QNetworkRequest::FollowRedirectsAttribute, тоді QNetworkAccessManager буде переходити по редиректах, поки не отримає підсумкову сторінку або не перевищить обмеження на кількість переходів. За замовчуванням кількість переходів обмежена 50-ма.
Встановлення атрибуту може здійснюватися так:
QNetworkRequest request; request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, QVariant(true));
Що стосується QNetworkReply::InsecureRedirectError, то сенс полягає в тому, щоб відстежити редирект на небезпечний протокол.
Помилки QNetworkReply::Proxy*
Наступні п'ять помилок аналогічні за характером помилок підключення до серверів без проксування.
QNetworkReply::ContentAccessDenied
У документації сказано, що дана помилка аналогічна помилці 401 HTTP, тобто потрібна авторизація, але вважаю, що дана помилка може виникати і у випадках отримання коду 403 і 407. Помилка 407 аналогічна помилці 401, але використовується для проксі-сервера. А помилка 403 є породжувальною для помилок 401 та 407.
QNetworkReply::AuthenticationRequiredError
Ця помилка характерна для протоколу HTTP. Справа в тому, що http протокол підтримує схеми автентичності. В даному випадку необхідно надсилати запит на сервер із встановленням логіну та пароля. Зауважу, що це безпосередньо означає те, що Ви можете написати додаток на Qt, який автентифікуватиметься на сайтах і виконувати певні дії на сайті вже в авторизованому режимі, тобто можна написати і бота для роботи на сайті.
Вирішення проблеми полягає в тому, щоб встановити логін та пароль користувача в QAuthenticator, який буде підмішувати облікові дані до запиту. Причому робитися це буде в автоматичному режимі за сигналом QNetworkAccessManager::authenticationRequired, при цьому логін та пароль будуть кешовані, тому сигнал не буде випускатися при кожному запиті.
connect(&m_manager,&QNetworkAccessManager::authenticationRequired, [this](QNetworkReply *rep, QAuthenticator* auth){ auth->setUser("username"); auth->setPassword("passwordd"); });
QNetworkReply::ContentReSendError
Провести будь-яку точну аналогію з кодами HTTP для цієї помилки є складним, оскільки викликатись вона може різними причинами.
QNetworkReply::ContentConflictError
Ця помилка відповідає помилці 409 Confilct у протоколі HTTP.
QNetworkReply::ContentGoneError
Ця помилка відповідає помилці 410 Gone (Видалений) у протоколі HTTP.
QNetworkReply::InternalServerError
Ця помилка відповідає помилці 500 Internal Server Error (Внутрішня помилка сервера) у протоколі http.
QNetworkReply::OperationNotImplementedError
Ця помилка відповідає помилці 501 Not Implemented (Не реалізовано) у протоколі http. Виникає така тоді, коли Ви намагаєтеся виконати, наприклад, запит POST до URL, яким сервер обробляє лише GET запити.
Таку поведінку можна зустріти, наприклад, у проекті Django . Якщо запит не реалізований, сервер з Django відправить порожню сторінку на POST запит з цим кодом.
QNetworkReply::ProtocolUnknownError
Така помилка, як QNetworkReply::ProtocolUnknownError, може виникнути через те, що запит було передано url без вказівки типу протоколу, тобто замість
http://www.example.com
було передано
//www.example.com
Така проблема може виникнути в тому випадку, якщо ви парсіте сторінки і виймаєте url зображень. Наприклад, на даному сайті адреси всіх зображень у статтях виглядають таким чином
/media/uploads/2017/02/03/testquickwidget.jpg
Тобто не вказується протокол та домен сайту. Тому якщо Ви витягнете всі адреси зображень зі сторінки, то не зможете завантажити зображення без додаткової обробки, а саме без встановлення домену і протоколу на початку рядка, отримавши цю помилку.
QNetworkReply::ServiceUnavailableError
Відповідає помилці 503 Service Unavailable («сервіс недоступний») у протоколі http
QNetworkReply::ProtocolInvalidOperationError
У цьому випадку протокол визначено, але точна відповідність помилці з протоколу http не простежується, щодо інших протоколів також може бути будь-що.
QNetworkReply::UnknownNetworkError
Найчастіший варіант того, чому може відповідати дана помилка є помилка шлюзу 502 Bad Gateway («поганий, помилковий шлюз») у протоколі http
QNetworkReply::UnknownProxyError
Також може бути помилка 502, але вже у варіанті з проксі-сервером
Ошибки QNetworkReply::UnknownContentError,QNetworkReply::ProtocolFailure, QNetworkReply::UnknownServerError
З цими помилками важко знайти робочу відповідність, буду радий підказці, якщо хтось стикався.
Приклад з виведенням помилки в qDebug
Ви можете перевірити помилку сигналу завершення запиту від QNetworkAccessManager у слоті, який підключається для обробки результату запиту.
manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &Downloader::onResult);
У цьому випадку є клас-обгортка над класом QNetworkAccessManager під назвою Downloader . Цей клас має слот onResult , який у свою чергу відповідає за обробку результату відповіді QNetworkAccessManager .
void Downloader::onResult(QNetworkReply *reply) { // Если в процессе получения данных произошла ошибка if(reply->error()){ // Сообщаем об этом и показываем информацию об ошибках qDebug() << "ERROR"; // Здесь получаем один из enum NetworkError, то есть код ошибки qDebug() << reply->error(); } else { // ToDo something } }
Unable to init SSL Context: Выдает приложение, что это может быть?
OpenSSL библиотеки возможно требуются. В этой статье есть ссылки, где скачать библиотеки OpenSSL.