Spec-Zone.ru › Qt 5.13

Программирование сетевых приложений с Qt

Модуль Qt Network предоставляет классы, позволяющие создавать TCP/IP-клиенты и серверы. Он предлагает классы низкого уровня, такие как QTcpSocket, QTcpServer и QUdpSocket, представляющие низкоуровневые сетевые понятия, а также классы высокого уровня, такие как QNetworkRequest, QNetworkReply и QNetworkAccessManager, для выполнения сетевых операций с использованием распространенных протоколов. Он также предоставляет классы, такие как QNetworkConfiguration, QNetworkConfigurationManager и QNetworkSession, которые реализуют управление носителем.

Классы Qt для сетевого программирования

Страница C++-классов Qt Network содержит список C++-классов в модуле Qt Network.

Операции на высоком уровне для HTTP и FTP

Network Access API — это набор классов для выполнения распространенных сетевых операций. API предоставляет абстракционный слой поверх конкретных операций и протоколов (например, получение и отправка данных по HTTP) и раскрывает только классы, функции и сигналы для общих или высокоуровневых понятий.

Сеть запросы представлены классом QNetworkRequest, который также действует как общий контейнер для информации, связанной с запросом, такой как заголовки и используемое шифрование. URL, указанный при создании объекта запроса, определяет используемый протокол для запроса. В настоящее время поддерживаются URL-адреса HTTP, FTP и локальных файлов для загрузки и скачивания.

Координацию сетевых операций выполняет класс QNetworkAccessManager. После создания запроса этот класс используется для его отправки и выдачи сигналов для отслеживания его выполнения. Менеджер также координирует использование куки для хранения данных на клиенте, запросы аутентификации и использование прокси-серверов.

Ответы на сетевые запросы представлены классом QNetworkReply, создаваемым классом QNetworkAccessManager при отправке запроса. Сигналы, предоставляемые классом QNetworkReply, можно использовать для отслеживания каждого ответа в отдельности, или разработчики могут выбрать использование сигналов менеджера для этой цели и отказаться от ссылок на ответы. Поскольку QNetworkReply является подклассом QIODevice, ответы могут обрабатываться синхронно или асинхронно; то есть как блокирующие или неблокирующие операции.

Каждое приложение или библиотека может создавать один или несколько экземпляров QNetworkAccessManager для обработки сетевого взаимодействия.

Использование TCP с QTcpSocket и QTcpServer

TCP (Transmission Control Protocol) — это сетевой протокол низкого уровня, используемый большинством интернет-протоколов, включая HTTP и FTP, для передачи данных. Это надежный, ориентированный на потоки, ориентированный на соединение транспортный протокол. Он особенно подходит для непрерывной передачи данных.

A TCP Stream

Класс QTcpSocket предоставляет интерфейс для TCP. Вы можете использовать QTcpSocket для реализации стандартных сетевых протоколов, таких как POP3, SMTP и NNTP, а также пользовательских протоколов.

Для начала передачи данных необходимо установить TCP-соединение с удаленным хостом и портом. После установления соединения IP-адрес и порт удаленного узла доступны через QTcpSocket::peerAddress() и QTcpSocket::peerPort(). В любой момент удаленный узел может разорвать соединение, и передача данных немедленно остановится.

QTcpSocket работает асинхронно и выдает сигналы для отчета об изменениях статуса и ошибках, как и QNetworkAccessManager. Он полагается на цикл событий для обнаружения входящих данных и автоматического сброса исходящих данных. Вы можете записать данные в сокет с помощью QTcpSocket::write(), а прочитать данные с помощью QTcpSocket::read(). QTcpSocket представляет два независимых потока данных: один для чтения и один для записи.

Поскольку QTcpSocket наследуется от QIODevice, вы можете использовать его с QTextStream и QDataStream. При чтении из QTcpSocket необходимо убедиться, что достаточно данных, вызвав QTcpSocket::bytesAvailable() предварительно.

Если вам необходимо обрабатывать входящие TCP-соединения (например, в приложении-сервере), используйте класс QTcpServer. Вызовите QTcpServer::listen() для настройки сервера и подключитесь к сигналу QTcpServer::newConnection(), который вызывается каждый раз при подключении клиента. В вашем слоте вызовите QTcpServer::nextPendingConnection() для принятия соединения и использования возвращённого QTcpSocket для связи с клиентом.

Хотя большинство его функций работают асинхронно, возможно использование QTcpSocket синхронно (т.е. блокирующее). Для получения блокирующего поведения вызовите функции waitFor...() QTcpSocket; они приостанавливают вызывающую нить до тех пор, пока не будет выпущен сигнал. Например, после вызова неблокирующей функции QTcpSocket::connectToHost() вызовите QTcpSocket::waitForConnected(), чтобы заблокировать нить до тех пор, пока не будет выпущен сигнал connected().

Синхронные сокеты часто приводят к коду с более простым потоком управления. Основным недостатком подхода waitFor...() является то, что события не будут обрабатываться во время блокирования функции waitFor...(). Если используется в потоке GUI, это может заморозить пользовательский интерфейс приложения. По этой причине рекомендуется использовать синхронные сокеты только в не-GUI потоках. При синхронном использовании QTcpSocket не требует цикла событий.

Примеры Fortune Client и Fortune Server показывают, как использовать QTcpSocket и QTcpServer для написания TCP-клиент-серверных приложений. Смотрите также пример Blocking Fortune Client для примера использования синхронного QTcpSocket в отдельном потоке (без использования цикла событий) и Threaded Fortune Server для примера многопоточного TCP-сервера с одним потоком на активного клиента.

Использование UDP с QUdpSocket

UDP (User Datagram Protocol) — это легкий, ненадежный, ориентированный на дейтаграммы, бессоединительный протокол. Он может быть использован, когда надежность не имеет большого значения. Например, сервер, который сообщает текущее время, может выбрать UDP. Если дейтаграмма с текущим временем потеряна, клиент может просто сделать новый запрос.

UDP Packets

Класс QUdpSocket позволяет отправлять и получать UDP-дейтаграммы. Он наследуется от QAbstractSocket и, следовательно, разделяет большую часть интерфейса QTcpSocket. Основное различие заключается в том, что QUdpSocket передает данные в виде дейтаграмм, а не непрерывного потока данных. Короче говоря, дейтаграмма — это пакет данных ограниченного размера (обычно меньше 512 байт), содержащий IP-адрес и порт отправителя и получателя дейтаграммы, а также передаваемые данные.

QUdpSocket поддерживает IPv4-вещание. Вещание часто используется для реализации протоколов обнаружения сети, таких как поиск узла в сети с наибольшим свободным объемом жесткого диска. Один узел передает дейтаграмму в сеть, которую получают все остальные узлы. Каждый узел, получивший запрос, отправляет ответ отправителю со своим текущим объемом свободного места на диске. Инициатор ожидает ответов от всех узлов и может выбрать сервер с наибольшим свободным объемом для хранения данных. Чтобы отправить дейтаграмму по вещанию, просто отправьте её по специальному адресу QHostAddress::Broadcast (255.255.255.255) или по широковещательному адресу вашей локальной сети.

QUdpSocket::bind() подготавливает сокет для приема входящих дейтаграмм, так же, как QTcpServer::listen() для TCP-серверов. При поступлении одной или нескольких дейтаграмм QUdpSocket выдает сигнал readyRead(). Вызовите QUdpSocket::readDatagram() для чтения дейтаграммы.

Примеры Broadcast Sender и Broadcast Receiver демонстрируют, как создать UDP-отправителя и UDP-получателя с помощью Qt.

QUdpSocket также поддерживает многоадресную рассылку. Примеры Multicast Sender и Multicast Receiver показывают, как использовать UDP-клиенты многоадресной рассылки.

Разрешение имен хостов с помощью QHostInfo

Перед установлением сетевого соединения QTcpSocket и QUdpSocket выполняют поиск имени, преобразуя имя хоста, к которому вы подключаетесь, в IP-адрес. Эта операция обычно выполняется с помощью протокола DNS (Domain Name Service).

QHostInfo предоставляет статическую функцию, которая позволяет выполнить такой поиск самостоятельно. Вызвав QHostInfo::lookupHost() с именем хоста, указателем QObject и сигнатурой слота, QHostInfo выполнит поиск имени и вызовет заданный слот, когда результаты будут готовы. Фактический поиск выполняется в отдельном потоке, используя собственные методы операционной системы для выполнения поиска имен.

QHostInfo также предоставляет статическую функцию QHostInfo::fromName(), которая принимает имя хоста в качестве аргумента и возвращает результаты. В этом случае поиск имени выполняется в том же потоке, что и вызывающий. Этот перегруз полезен для приложений, не использующих GUI, или для выполнения поиска имен в отдельном, не-GUI потоке. (Вызов этой функции в потоке GUI может привести к зависанию пользовательского интерфейса во время блокирования функции при выполнении поиска.)

Поддержка сетевых прокси

Связь с сетью в Qt может осуществляться через прокси-серверы, которые направляют или фильтруют сетевой трафик между локальными и удалёнными подключениями.

Индивидуальные прокси-серверы представлены классом QNetworkProxy, который используется для описания и настройки подключения к прокси-серверу. Поддерживаются типы прокси-серверов, работающие на разных уровнях сетевой связи, при этом поддержка SOCKS 5 позволяет проксировать сетевой трафик на низком уровне, а проксирование HTTP и FTP работает на уровне протокола. Дополнительную информацию см. в QNetworkProxy::ProxyType.

Проксирование может быть включено на основе каждого сокета или для всех сетевых коммуникаций в приложении. Недавно открытый сокет может использовать прокси, вызвав функцию QAbstractSocket::setProxy() перед подключением. Включение проксирования для всех последующих подключений сокетов на уровне приложения может быть выполнено с помощью функции QNetworkProxy::setApplicationProxy().

Прокси-фабрики используются для создания политик использования прокси-серверов. QNetworkProxyFactory предоставляет прокси-серверы на основе запросов для определённых типов прокси. Сами запросы закодированы в объектах QNetworkProxyQuery, которые позволяют выбирать прокси-серверы на основе ключевых критериев, таких как назначение прокси-сервера (TCP, UDP, TCP-сервер, запрос URL), локальный порт, удалённый хост и порт, и используемый протокол (HTTP, FTP и т.д.).

QNetworkProxyFactory::proxyForQuery() используется для непосредственного запроса фабрики. Политику проксирования на уровне приложения можно реализовать, передав фабрику в QNetworkProxyFactory::setApplicationProxyFactory(), а пользовательскую политику проксирования можно создать, наследуя класс QNetworkProxyFactory; подробную информацию см. в документации класса.

Поддержка управления носителем

Управление носителем контролирует состояние подключения устройства таким образом, что приложение может запускать или останавливать сетевые интерфейсы и прозрачно перемещаться между точками доступа.

Класс QNetworkConfigurationManager управляет списком сетевых конфигураций, известных устройству. Сетевая конфигурация описывает набор параметров, используемых для запуска сетевого интерфейса, и представлена классом QNetworkConfiguration.

Сетевой интерфейс запускается путём открытия QNetworkSession на основе заданной сетевой конфигурации. В большинстве случаев создание сетевой сессии на основе платформенно заданной по умолчанию сетевой конфигурации является подходящим вариантом. По умолчанию сетевая конфигурация возвращается функцией QNetworkConfigurationManager::defaultConfiguration().

На некоторых платформах для выполнения любых сетевых операций приложение должно открыть сетевую сессию. Это можно проверить по наличию флага QNetworkConfigurationManager::NetworkSessionRequired в значении, возвращаемом функцией QNetworkConfigurationManager::capabilities().

См. также Управление носителем.

© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/qtnetwork-programming.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API