Spec-Zone.ru › Qt 5.15

Программирование сетей с Qt

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

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

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

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

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

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

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

Ответы на запросы в сеть представлены классом 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 с помощью 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; см. документацию класса для получения подробностей.

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

Spec-Zone.ru

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