Qt网络编程概述(一)

分享主题

Qt网络编程概述(一)
Qt网络编程之QTCPSocket和QTCPServer实例(二)
Qt网络编程之QUdpSocket实例(三)

Qt网络编程概述

QtNetWork模块提供了若干类支持TCP/IP客户端服务器端的开发。有如下两类:

  • 低级网络操作:QTcpSocket/QTcpServer/QUdpSocket
  • 高级网络操作:QNetworkRequest/QNetworkReply/QNetworkAccessManager

TCP/IP详解

Qt网络编程相关类

类名 作用
QAbstractSocket The base functionality common to all socket types
QTcpServer TCP-based server
QTcpSocket TCP socket
QUdpSocket UDP socket
QNetworkAccessManager Allows the application to send network requests and receive replies
QNetworkReply Contains the data and headers for a request sent with QNetworkAccessManager
QNetworkRequest Holds a request to be sent with QNetworkAccessManager
QNetworkCookie Holds one network cookie
QNetworkCookieJar Implements a simple jar of QNetworkCookie objects
QNetworkSession Control over the system’s access points and enables session management for cases when multiple clients access the same access point
QLocalSocket Local socket
QLocalServer Local socket based server
QHttpPart Holds a body part to be used inside a HTTP multipart MIME message
QHttpMultiPart Resembles a MIME multipart message to be sent over HTTP
QHostInfo Static functions for host name lookups
QHostAddress IP address

高级网络操作-HTTP/FTP

Qt网络编程提供了大量的API用于网络操作。API为特定的操作和协议提供了一个抽象层(如通过HTTP收发数据)。主要有如下几大核心类:

  • QNetworkRequest网络请求:充当请求关联信息的容器,如请求头、加密等。当请求对象构造时指定了URL,也就确定了请求协议。目前支持使用HTTP/FTP/本地文件URL上传下载文件。

  • QNetworkReply请求响应:当用户请求发出后,该对象由QNetworkAccessManager创建。QNetworkReply发出的信号可独立的监控每个请求响应,或者用QNetworkAccessManager的信号替代。QNetworkReply是QIODevice的子类,因此响应可以被同步或异步的处理(阻塞或非阻塞)。

  • QNetworkAccessManager操作管理:请求创建后,管理类会分发请求,然后对外发送信号标识请求进度。还可使用cookies在客户端存储数据、请求认证、代理使用。

TCP编程QTcpSocket/QTcpServer

TCP(传输控制协议)是被大多网络协议使用的低级别协议,如HTTP/FTP。它是可靠的、面向流的、面向连接的传输协议。特别适合于连续的数据传输。QTcpSocket类为TCP提供了若干接口。可用QTcpSocket实现标准网络协议,如POP3、SMTP、NNTP、自定义协议。

Qt网络编程概述(一)_第1张图片

在开始数据转移前,需要与远程主机和端口建立TCP连接。一旦建立连接,对等方的IP地址和端口可通过QTcpSocket::peerAddress()和QTcpSocket::peerPort()获取。在任意时刻,对等方可以关闭连接,此时数据转移会立即终止。

QTcpSocket以异步的方式工作,并通过发送信号报告状态的改变及错误,类似于QNetworkAccessManger。通过事件循环检测输入数据,并自动的Flush输出数据。可使用QTcpSocket::write()往socket中写入数据,QTcpSocket::read()向socket中写入数据。QTcpSocket有两个独立的数据流:读和写。由于QTcpSocket继承自QIODevice,可以和QTextStream、QDataStream一块使用。当从QTcpSocket读取数据时,可调用QTcpSocket::bytesAvailable()确保有足够的数据。

QTcpServer类处理接收到的TCP连接。一般使用逻辑如下:

  1. 调用QTcpServer::listen()启动服务端并监听;
  2. 每当接收到客户端的请求,就会发送QTcpServer::newConnection()信号;
  3. 在槽函数中,调用QTcpServer::nextPendingConnection()接受请求,并用返回的QTcpSocket与客户端通信。

QTcpSocket类客户端建立TCP连接。一般使用逻辑如下:

  1. 调用QTcpSocket::connectToHost连接到主机;
  2. 连接readyRead()信号槽;
  3. 在槽函数中与服务端交互。

尽管QTcpSocket大部分函数是以异步的方式工作,但仍可用同步的方式处理(阻塞)。为了以阻塞方式,需调用QTcpSocket的waitFor…()函数,它会挂起调用线程直到结束信号被发送。例如,调用非阻塞函数QTcpSocket::connectToHost()时,调用QTcpSocket::waitForConnected()阻塞线程直到connected()信号被发射。QTcpSocket的waitFor…()的弊端也很明显:当阻塞时,事件不会被处理,如果在GUI线程中,会阻塞应用程序的界面。因此,推荐在非GUI线程中使用同步sockets(同步处理时,QTcpSocket无需事件循环)。

UDP编程QUdpSocket

UDP(用户数据报协议)是一个轻量级、不可靠的、面向数据报的、无连接的协议。当可靠性不是很重要、速度很重要时,可使用该协议。例如,服务器端选择UDP报告每天的时间,如果期间的某个数据报丢失,客户端可另外请求数据。

Qt网络编程概述(一)_第2张图片

QUdpSocket类允许收发数据报。与TCP的主要区别是:UDP传输的是数据包而不是连续的数据流。数据包是大小有限的数据单元(通常小于512字节),除了包含的传输数据外,还包含收发对象的IP地址和端口号。一般使用逻辑如下:

  1. QUdpSocket::bind()接受传入的数据包;
  2. 接收到数据包后,QUdpSocket发送readyRead()信号;
  3. 调用QUdpSocket::readDatagram()读取数据。

解析主机名QHostName

在建立网络连接前,QTcpSocket和QUdpSocket执行域名查找,将连接的主机名转化为IP地址(DNS)。提供如下两种方式:

  1. QHostInfo::lookupHost() 异步查找,通过信号槽机制,查找在单独的线程中实现。
  2. QHostInfo::forName() 同步查找,在调用者所在线程实行查找。注意在GUI线程中调用,可能会阻塞界面。

代码示例如下:

头文件

//
//主机信息测试验证
#include 
#include 

class HostInfoDemo : public QObject
{
	Q_OBJECT
	
private slots:
	void lookUp(const QHostInfo& oHostInfo);
};

void testHostInfoDemo();

源文件

#include "HostInfoDemo.h"
#include 

void HostInfoDemo::lookUp(const QHostInfo& oHostInfo)
{
	if (oHostInfo.error() != QHostInfo::NoError)
	{
		qDebug() << "failed: " << oHostInfo.errorString();
		return;
	}

	const auto addresses = oHostInfo.addresses();
	for (const QHostAddress &oAddress : addresses)
	{
		qDebug() << "asynchronous Found address: " << oAddress.toString();
	}
}

void testHostInfoDemo()
{
	//异步方式
	qDebug() << QStringLiteral("异步方式...");
	HostInfoDemo* pDemo = new HostInfoDemo;
	QHostInfo::lookupHost("www.kde.org", pDemo, SLOT(lookUp(QHostInfo)));

	//同步方式
	qDebug() << QStringLiteral("同步方式...");
	QHostInfo oHostInfo = QHostInfo::fromName("www.kde.org");
	const auto addresses = oHostInfo.addresses();
	for (const QHostAddress &oAddress : addresses)
	{
		qDebug() << "synchronous Found address: " << oAddress.toString();
	}
}

输出信息

"异步方式..."
"同步方式..."
synchronous Found address:  "91.189.93.5"
asynchronous Found address:  "91.189.93.5"

你可能感兴趣的:(Qt剖析)