Qt网络模块提供了允许您编写TCP / IP客户端和服务器的类。它提供了代表低级网络概念的低级类(例如QTcpSocket,QTcpServer和QUdpSocket),以及高级类(例如QNetworkRequest,QNetworkReply和QNetworkAccessManager)来使用通用协议执行网络操作。它还提供实现承载管理的类,例如QNetworkConfiguration,QNetworkConfigurationManager和QNetworkSession。
Qt的网络编程课程
“ Qt Network C ++ Classes”页面包含Qt Network中C ++类的列表。
HTTP和FTP的高级网络操作
网络访问API是用于执行常见网络操作的类的集合。API在使用的特定操作和协议(例如,通过HTTP获取和发布数据)上提供了一个抽象层,并且仅公开了用于通用或高级概念的类,函数和信号。
网络请求由QNetworkRequest类表示,该类也充当与请求相关联的信息(例如,任何标头信息和所使用的加密)的通用容器。构造请求对象时指定的URL确定用于请求的协议。当前,支持HTTP,FTP和本地文件URL进行上载和下载。
网络操作的协调由QNetworkAccessManager类执行。创建请求后,将使用此类来分派请求并发出信号以报告其进度。管理器还协调使用Cookie来存储客户端上的数据,身份验证请求以及代理的使用。
对网络请求的答复由QNetworkReply类表示。这些是由QNetworkAccessManager在调度请求时创建的。QNetworkReply提供的信号可用于单独监视每个答复,或者开发人员可以选择为此目的使用管理器的信号,而放弃对答复的引用。由于QNetworkReply是QIODevice的子类,因此可以同步或异步地处理答复。即作为阻塞或非阻塞操作。
每个应用程序或库都可以创建一个或多个QNetworkAccessManager实例来处理网络通信。
将TCP与QTcpSocket和QTcpServer一起使用
TCP(传输控制协议)是大多数Internet协议(包括HTTP和FTP)用于数据传输的低级网络协议。它是一种可靠的,面向流,面向连接的传输协议。它特别适合连续数据传输。
QTcpSocket类为TCP提供了一个接口。QTcpSocket可以实现POP3、SMTP、NNTP等标准网络协议,也可以实现自定义网络协议。
必须先建立与远程主机和端口的TCP连接,然后才能开始任何数据传输。建立连接后,即可通过QTcpSocket :: peerAddress()和QTcpSocket :: peerPort()获得对等方的IP地址和端口。对等方可以随时关闭连接,然后数据传输将立即停止。
QTcpSocket异步工作,并发出信号来报告状态更改和错误,就像QNetworkAccessManager一样。它依靠事件循环来检测输入数据并自动刷新输出数据。您可以使用QTcpSocket :: write()将数据写入套接字,并使用QTcpSocket :: read()读取数据。QTcpSocket表示两个独立的数据流:一个用于读取,一个用于写入。
由于QTcpSocket继承了QIODevice,因此可以将其与QTextStream和QDataStream一起使用。从QTcpSocket读取时,必须通过事先调用QTcpSocket :: bytesAvailable()来确保有足够的数据可用。
如果您需要处理传入的TCP连接(例如,在服务器应用程序中),请使用QTcpServer类。调用QTcpServer :: listen()建立服务器,并连接到QTcpServer :: newConnection()信号,该信号对于每个连接的客户端发出一次。在您的插槽中,调用QTcpServer :: nextPendingConnection()接受连接,并使用返回的QTcpSocket与客户端进行通信。
尽管它的大多数功能都是异步工作的,但也可以同步使用QTcpSocket(即阻塞)。要获得阻塞行为,请调用QTcpSocket的waitFor ...()函数;它们挂起调用线程,直到发出信号为止。例如,在调用非阻塞QTcpSocket :: connectToHost()函数之后,调用QTcpSocket :: waitForConnected()阻塞线程,直到发出connect ()信号为止。
同步套接字通常导致代码具有更简单的控制流程。waitFor ...()方法的主要缺点是,在waitFor ...()函数阻塞时不会处理事件。如果在GUI线程中使用,这可能会冻结应用程序的用户界面。因此,我们建议您仅在非GUI线程中使用同步套接字。同步使用时,QTcpSocket不需要事件循环。
在 Fortune Client和 Fortune Server实例展示了如何使用QTcpSocket和QTcpServer编写的TCP客户机-服务器应用程序。另请参见Blocking Fortune Client 示例了解如何在单独的线程中使用同步QTcpSocket(不使用事件循环)的示例。以及Threaded Fortune Server示例学习每个活动客户端一个线程的多线程TCP服务器
将UDP与QUdpSocket一起使用
UDP(用户数据报协议)是一种轻量级,不可靠,面向数据报的无连接协议。当可靠性不重要时可以使用它。例如,报告时间的服务器可以选择UDP。如果丢失了一天中的数据报,则客户端可以简单地发出另一个请求。
该QUdpSocket提供类允许您发送和接收UDP数据包。它继承了QAbstractSocket,因此它共享QTcpSocket的大部分接口。主要区别在于QUdpSocket将数据作为数据报而不是连续的数据流进行传输。简而言之,数据报是有限大小的数据包(通常小于512字节),除了要传输的数据外,还包含数据报的发送方和接收方的IP地址和端口。
QUdpSocket支持IPv4广播。广播通常用于实现网络发现协议,例如查找网络上的哪个主机具有最大的可用硬盘空间。一台主机向所有其他主机接收的网络广播数据报。每个接收到请求的主机然后将其当前的可用磁盘空间量发送给发件人答复。始发者等待直到收到所有主机的答复,然后可以选择具有最大可用空间的服务器来存储数据。要广播数据报,只需将其发送到特殊地址QHostAddress :: Broadcast(255.255.255.255),或发送到本地网络的广播地址。
QUdpSocket :: bind()准备用于接受传入数据报的套接字,就像TCP服务器的QTcpServer :: listen()一样。每当一个或多个数据报到达时,QUdpSocket就会发出readyRead()信号。调用QUdpSocket :: readDatagram()读取数据报。
Broadcast Sender 和 Broadcast Receiver 示例展示了如何使用Qt编写UDP发送端和UDP接收端。
QUdpSocket还支持多播。“ Multicast Sender ”和“ Multicast Receiver ”示例显示了展示了如何使用Qt写UDP组播客户端。
使用QHostInfo解析主机名
在建立网络连接之前,QTcpSocket和QUdpSocket执行名称查找,将要连接的主机名转换为IP地址。该操作通常使用DNS(域名服务)协议进行。
QHostInfo提供了一个静态函数,允许您自己执行这样的查找。通过使用主机名、QObject指针和插槽签名调用QHostInfo :: lookupHost(),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 ; 有关详细信息,请参见类文档。