用 Qt 进行网络编程

Qt Network 模块提供了允许编写 TCP/IP 客户端和服务器的类。它提供的低级类,如 QTcpSocket , QTcpServer and QUdpSocket 表示低级网络概念,和高级类,如 QNetworkRequest , QNetworkReply and QNetworkAccessManager to perform network operations using common protocols. It also offers classes such as QNetworkConfiguration , QNetworkConfigurationManager and QNetworkSession that implement bearer management.

Qt 网络编程类

Qt Network C++ 类 页面包含在 Qt 网络中的 C++ 类列表。

高级 HTTP FTP 网络操作

网络访问 API 是用于履行常见网络操作的一批类。API 提供的抽象层覆盖特定操作和所用协议 (例如:通过 HTTP 获取和张贴数据),并仅为一般 (或高级) 概念暴露类、函数及信号。

网络请求的表示是通过 QNetworkRequest 类,还充当与请求关联的信息 (譬如:任何 Header 头信息和使用加密) 的通用容器。构造请求对象时指定的 URL 确定请求使用的协议。目前,上传和下载支持 HTTP、FTP 和本地文件 URL。

网络操作协调的履行通过 QNetworkAccessManager 类。一旦请求被创建,此类用于分派它并发射信号来报告其进度。管理器还协调使用 Cookie Cookie 在客户端存储数据、身份验证请求及使用代理。

网络请求响应的表示通过 QNetworkReply 类;这些被创建由 QNetworkAccessManager 当分派请求时。信号的提供通过 QNetworkReply 可以用于单独监视每个回复,或开发者可以选取使用管理器信号代替此目的并丢弃回复引用。由于 QNetworkReply 是子类化的 QIODevice ,可以同步或异步处理回复;即:阻塞或非阻塞操作。

每个应用程序或库均可以创建一个或多个实例化的 QNetworkAccessManager 来处理网络通信。

以 QTcpSocket 和 QTcpServer 使用 TCP

TCP (传输控制协议) 是用于大多数 Internet 协议 (包括 HTTP 和 FTP) 的低级数据传输网络协议。它是可靠的、面向流的、面向连接的传输协议。它尤其适合于连续数据传输。

A TCP Stream

QTcpSocket 类为 TCP 提供接口。可以使用 QTcpSocket 以实现标准网络协议 (譬如:POP3、SMTP 和 NNTP) 及自定义协议。

必须建立到远程主机和端口的 TCP 连接,在开始传输任何数据之前。一旦建立连接,对等方的 IP 地址和端口就是可用的透过 QTcpSocket::peerAddress () 和 QTcpSocket::peerPort ()。在任何时候,对等方都可以关闭连接,然后数据传输将立即停止。

QTcpSocket 异步工作并发射信号以报告状态改变和错误,就像 QNetworkAccessManager 。它依赖事件循环来检测传入数据并自动刷新传出数据。可以把数据写入套接字使用 QTcpSocket::write (),和读取数据使用 QTcpSocket::read (). QTcpSocket 表示 2 个独立数据流:一个用于读取,一个用于写入。

由于 QTcpSocket 继承 QIODevice ,可以使用它采用 QTextStream and QDataStream 。当读取自 QTcpSocket ,必须确保有足够的可用数据通过调用 QTcpSocket::bytesAvailable () 事先。

若需要处理传入的 TCP 连接 (如:在服务器应用程序中),使用 QTcpServer 类。调用 QTcpServer::listen () 去设置服务器,并连接到 QTcpServer::newConnection () 信号,对每个连接客户端发射一次。在槽中,调用 QTcpServer::nextPendingConnection () 以接受连接并使用返回的 QTcpSocket 来与客户端通信。

尽管其大多数函数是异步工作的,它是可能的使用 QTcpSocket 同步 (即:阻塞)。要获得阻塞行为,调用 QTcpSocket 的 waitFor...() 函数;它们挂起调用线程直到信号被发射为止。例如,先调用非阻塞 QTcpSocket::connectToHost () 函数,调用 QTcpSocket::waitForConnected () 以阻塞线程直到 connected() 信号已被发射。

同步套接字常导致代码具有更简单的控制流。waitFor...() 方式的主要缺点是当 waitFor...() 函数阻塞时事件不会被处理。若用于 GUI 线程,这可能冻结应用程序的用户界面。由于此原因,推荐只在非 GUI 线程中使用同步套接字。当同步使用时, QTcpSocket 不要求事件循环。

Fortune 客户端 and Fortune 服务器 范例展示如何使用 QTcpSocket and QTcpServer 编写 TCP 客户端-服务器应用程序。另请参阅 阻塞 Fortune 客户端 范例了解如何使用同步 QTcpSocket 在单独线程 (不使用事件循环),和 线程化 Fortune 服务器 范例了解每个活动客户端采用一线程的多线程 TCP 服务器。

以 QUdpSocket 使用 UDP

UDP (用户数据报协议) 是轻量、不可靠、面向数据报的无连接协议。可以使用它,当可靠性不重要时。例如,报告每天时间的服务器可以选择 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 () 以读取数据报。

广播发送器 and 广播接收器 范例展示如何使用 Qt 编写 UDP 发送器和 UDP 接收器。

QUdpSocket 还支持多点播送。 多点播送发送器 and 多点播送接收器 范例展示如何使用写入 UDP 多点播送客户端。

使用 QHostInfo 解析主机名

在建立网络连接之前, QTcpSocket and QUdpSocket 履行名称查找,把要连接的主机名转换成 IP 地址。通常使用 DNS (域名服务) 协议履行此操作。

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 ;见类文档编制了解细节。

承载管理支持

Bearer Management controls the connectivity state of the device such that the application can start or stop network interfaces and roam transparently between access points.

QNetworkConfigurationManager class manages the list of network configurations known to the device. A network configuration describes the set of parameters used to start a network interface and is represented by the QNetworkConfiguration 类。

A network interface is started by openning a QNetworkSession based on a given network configuration. In most situations creating a network session based on the platform specified default network configuration is appropriate. The default network configuration is returned by the QNetworkConfigurationManager::defaultConfiguration () 函数。

On some platforms it is a platform requirement that the application open a network session before any network operations can be performed. This can be tested by the presents of the QNetworkConfigurationManager::NetworkSessionRequired flag in the value returned by the QNetworkConfigurationManager::capabilities () 函数。

另请参阅 承载管理 .