Network Programming with Qt
Qt网络模块提供编写TCP/IP客户端和服务器的类. 它不仅提供底层类 (QTcpSocket, QTcpServer, QUdpSocket), 也提供高级类(如 QNetworkRequest, QNetworkReply, QNetworkAccessManager), 还提供网络管理类 (QNetworkConfiguration, QNetworkConfigurationManager, QNetworkSession).
Qt的网络编程类
The Qt Network C++ Classes 页面包含Qt网络模块所有的C++类.
支持HTTP及FTP的高级网络操作
网络访问API是处理网络操作的类集合. 网络访问API是用于执行常见网络操作的类的集合。API在所使用的特定操作和协议上提供了一个抽象层 (例如,通过HTTP获取和发布数据), 并且仅公开一般或高级概念的类、函数和信号.
网络请求由 QNetworkRequest 表示, 该类还充当与请求相关联的信息的通用容器, 例如任何标头信息和使用的加密. 构造请求对象时指定的URL决定了用于请求的协议. 目前支持HTTP, FTP和本地文件URL进行上传和下载.
网络操作的协调由 QNetworkAccessManager 执行. 一旦创建了一个请求, 这个类就用于调度它并发出信号来报告它的进度. 管理器还协调 cookies 在客户端上存储数据的使用, 身份验证请求和代理的使用.
对网络请求的回复由 QNetworkReply 表示; 这些是 QNetworkAccessManager 在发送请求时创建的. QNetworkReply 提供的信号可以用于单独监控每个回复, 或者开发人员可以选择将管理器的信号用于此目的, 并放弃对回复的引用. 由于 QNetworkReply 是 QIODevice的子类, 因此可以同步或异步处理回复; 即., 作为阻塞或非阻塞操作.
每个应用程序或库都可以创建一个或多个 QNetworkAccessManager 实例处理网络通信.
通过QTcpSocket和QTcpServer使用TCP
TCP (Transmission Control Protocol) 是低级的网络协议, 也是多数网络协议的基础, 如HTTP和FTP. 它是一种可靠的, 面向流的, 面向连接的传输协议, 特别适合数据的连续传输.
QTcpSocket 提供TCP接口. 你可以使用 QTcpSocket 实现标准的网络协议, 如 POP3, SMTP, NNTP, 也可以自定义协议.
传输数据之前, 你必须使用主机和端口建立TCP连接. 一旦建立连接, C/S端都可以调用 QTcpSocket::peerAddress() 和 QTcpSocket::peerPort()获取彼此的地址和端口. 任意时刻, 任何一方都可以关闭连接, 数据传输立即中止.
类似 QNetworkAccessManager, QTcpSocket 异步工作, 并在状态更改和发生错误时, 发出信号. QTcpSocket依赖事件循环检测传入数据, 自动刷新传出数据. 你可以调用 QTcpSocket::write()将数据写入套接字, 使用 QTcpSocket::read()从套接字读取数据. QTcpSocket 代表2个独立的数据流: 分别用于读写.
QTcpSocket 继承自 QIODevice, 你可以将其与 QTextStream 和 QDataStream一起使用. 从 QTcpSocket读取数据时, 你必须先调用 QTcpSocket::bytesAvailable() 确保有足够的数据可用.
如果你需要处理传入的TCP连接 (如., 编写服务器程序), 使用 QTcpServer. 服务器调用 QTcpServer::listen() 监听客户端, 并连接 QTcpServer::newConnection() 信号, 每次客户端连接都会发出该信号. 在槽函数中, 调用 QTcpServer::nextPendingConnection() 接受连接, 并利用返回值 QTcpSocket 与客户端通信.
尽管多数函数是异步方式, 但也可以使用同步方式(即阻塞). 调用 QTcpSocket的 waitFor...() 函数获取阻塞行为; 这类函数会挂起调用线程, 直到收到信号. 例如, 调用异步函数 QTcpSocket::connectToHost() 函数后, 调用 QTcpSocket::waitForConnected() 阻塞线程, 直到收到 connected() 信号.
同步套接字使代码的控制流更加简练, 缺点是waitFor...()函数在等待时不会处理事件循环. 如果在GUI线程使用, 这种方式可能阻塞用户界面. 因此, 我们建议你仅在非GUI线程使用同步套接字. 采用同步方式时, QTcpSocket 不需要事件循环.
Fortune Client 和 Fortune Server 示例展示如何使用 QTcpSocket 和 QTcpServer 编写客户端-服务端应用程序. Blocking Fortune Client 示例展示如何在单独的线程使用 QTcpSocket 同步方式(不使用事件循环), Threaded Fortune Server 示例展示如何编写多线程TCP服务器, 每个线程与一个客户端通信.
通过QUdpSocket使用UDP
UDP (User Datagram Protocol) 是一个轻量级, 不可靠, 面向数据报的无连接协议. 可靠性无要求的情况下使用UDP. 如, 报告时间的服务器可以采用UDP. 如果时间数据报丢失, 客户端可以发起另一个简单请求.
QUdpSocket 允许你收发UDP数据报. 由于QUdpSocket继承自 QAbstractSocket, 所有大部分接口与 QTcpSocket一样. QUdpSocket 与 QTcpSocket 的主要区别是将数据作为数据报传输, 而不是作为连续的数据流传输. 简而言之, 数据报是一个有限大小(通常小于512字节)的数据包. 除传输数据外, 还包含数据报的发送和接受的IP地址, 端口.
QUdpSocket 支持IPv4广播. 广播常用于实现网络发现协议, 如查找网络上哪个主机的硬盘空间最多. 一个主机向网络广播数据报, 所有其他主机都接收该数据报. 每个接收到请求的主机都将当前可用磁盘空间量发送回发送者. 发送方等待, 直到收到所有主机的回复, 然后选择最有最多可用空间的服务器存储数据. 要广播数据报, 只需将发送地址设为 QHostAddress::Broadcast (255.255.255.255), 或局域网的广播地址.
QUdpSocket::bind() 准备接收数据报的套接字, 类似 QTcpServer::listen() . 每当一个或多个数据报到达时, QUdpSocket 都会发出 readyRead() 信号. 调用 QUdpSocket::readDatagram() 读取数据.
Broadcast Sender 和 Broadcast Receiver 示例展示如何利用Qt编写UDP发送和接收软件.
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 表示, 这个类描述和配置与代理的连接. Qt支持不同级别的网络通信代理类型. SOCKS5支持低级别的网络代理, HTTP和FTP支持协议级别代理. 详参 QNetworkProxy::ProxyType.
代理可以在每个套接字启动, 也可以针对一个应用程序的所有网络通信. 新打开的套接字在连接前, 先调用 QAbstractSocket::setProxy() 函数设置代理. 调用 QNetworkProxy::setApplicationProxy() 函数设置应用程序范围的代理, 应用程序的所有套接字启用代理.
代理工厂创建代理策略. QNetworkProxyFactory 基于对特定代理类型的查询提供代理. 查询本身编码在 QNetworkProxyQuery 对象中, 这些对象使代理能够根据关键标准进行选择, 例如代理的目的(TCP,UDP,TCP服务器,URL请求), 本地端口, 远程主机和端口以及使用的协议(HTTP, FTP等).
QNetworkProxyFactory::proxyForQuery() 直接查询工厂. 调用 QNetworkProxyFactory::setApplicationProxyFactory() 设置应用程序范围的代理策略, 且可以通过子类化 QNetworkProxyFactory创建自定义代理策略.
Bearer Management Support
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.
The 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 class.
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() function.
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() function.