HTTP 网络的请求发送和响应处理

通常需要包含以下头文件:

  1. QNetworkAccessManager: 用于管理网络请求
  2. QNetworkRequest: 用于构建并发送请求(例如设置URL、HTTP头等)
  3. QNetworkReply: 用于接收响应
  4. QUrl: 用于处理请求的URL

注:qmake 中添加 QT += network

运行演示.gif

代码地址:HTTP 和 JSON

文章指引:JSON 处理

finished 信号意味着什么 ?

待我们发送请求之后,直到对端响应才会继续往下执行代码:

1
QNetworkReply* response_ = httpManager_->get(request_);

响应之后,QNetworkReply 会发出 finished 信号,这个信号的触发并不意味着请求一定成功,它只是表示网络请求的处理已经完成,所有数据都已接收,无论请求的结果是成功还是失败。要判断请求是否成功,需要检查 QNetworkReply 对象的状态。

我们先判断此次请求是否有错误(QNetworkReply::NoError),如果有就打印错误情况,否则就继续我们的代码逻辑。

1
2
3
4
5
6
7
connect(response_,&QNetworkReply::finished,this,[response_,this](){
if(response_->error() == QNetworkReply::NoError){ // 没有发送错误
emit http_finished(response_);
}else{
qDebug()<<response_->error(); // 打印失败情况
}
});

读取对端响应

此代码中是 readAll 读取全部的数据,然后保存到 QByteArray 中,但是如果传来的数据很大,这未必是合理的处理方式。对几种常用的方式简单总结:

  • readAll() 是最简单的方式,但可能在数据较大时消耗较多内存。
  • read()readLine() 提供了逐步读取的控制,适合处理流式或分块数据。
  • bytesAvailable() 让你可以根据数据量动态决定读取策略,适合需要优化性能的场景。

(一)read:逐步读取接收的数据,参数是要读取的字节数。你可以调用它多次来读取一部分数据

1
QByteArray chunk = reply->read(1024);  // 读取1024字节

适用场景:当数据量较大或者需要按块处理时,read() 允许你控制读取的数据大小。例如处理大型文件或流式数据时,可以避免一次性占用过多内存。

(二)readAll:一次性读取所有可用的数据

1
QByteArray allData = reply->readAll();  // 读取所有数据

适用场景:当你知道数据量较小,或者你不关心数据的大小时,readAll() 是最简单的方式。它会把所有接收到的数据存储在一个字节数组中。

(三)readLine:读取一行数据,行以换行符(\n)或回车换行符(\r\n)作为结尾。它会读取直到遇到这些字符或达到给定字节数

1
QByteArray line = reply->readLine();

适用场景:适合处理以行结构组织的文本数据(例如 HTTP 响应头、CSV 文件)

(四)bytesAvailable:返回当前可以从缓冲区中读取的字节数。你可以使用它来查看是否有足够的数据可供读取

1
qint64 availableBytes = reply->bytesAvailable();

用于判断是否有足够数据来决定使用 read()readLine()