[Qt教程] 第32篇 网络(二)HTTP
生活随笔
收集整理的這篇文章主要介紹了
[Qt教程] 第32篇 网络(二)HTTP
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
[Qt教程]?第32篇 網(wǎng)絡(luò)(二)HTTP
??|?查看: 637|?回復(fù): 8| HTTP 版權(quán)聲明 該文章原創(chuàng)于作者yafeilinux,轉(zhuǎn)載請(qǐng)注明出處! 導(dǎo)語 ? ?? ?? HTTP(HyperText Transfer Protocol,超文本傳輸協(xié)議)是一個(gè)客戶端和服務(wù)器端請(qǐng)求和應(yīng)答的標(biāo)準(zhǔn)。在Qt的網(wǎng)絡(luò)模塊中提供了網(wǎng)絡(luò)訪問接口來實(shí)現(xiàn)HTTP編程。網(wǎng)絡(luò)訪問接口是執(zhí)行一般的網(wǎng)絡(luò)操作的類的集合,該接口在特定的操作和使用的協(xié)議(例如,通過HTTP進(jìn)行獲取和發(fā)送數(shù)據(jù))上提供了一個(gè)抽象層,只為外部暴露出了類、函數(shù)和信號(hào)。 上一節(jié)中我們已經(jīng)提到過了,現(xiàn)在Qt中使用QNetworkAccessManager類和QNetworkReply類來進(jìn)行HTTP的編程。網(wǎng)絡(luò)請(qǐng)求由QNetworkRequest類來表示,它也作為與請(qǐng)求有關(guān)的信息(例如,任何頭信息和使用加密)的容器。在創(chuàng)建請(qǐng)求對(duì)象時(shí)指定的URL決定了請(qǐng)求使用的協(xié)議,目前支持HTTP、FTP和本地文件URLs的上傳和下載。QNetworkAccessManager類用來協(xié)調(diào)網(wǎng)絡(luò)操作,每當(dāng)一個(gè)請(qǐng)求創(chuàng)建后,該類用來調(diào)度它,并發(fā)射信號(hào)來報(bào)告進(jìn)度。該類還協(xié)調(diào)cookies的使用,身份驗(yàn)證請(qǐng)求,及其代理的使用等。對(duì)于網(wǎng)絡(luò)請(qǐng)求的應(yīng)答使用QNetworkReply類表示,它會(huì)在請(qǐng)求被完成調(diào)度時(shí)由QNetworkAccessManager來創(chuàng)建。QNetworkReply提供的信號(hào)可以用來單獨(dú)的監(jiān)視每一個(gè)應(yīng)答。 ? ?? ? 下面我們先講解一個(gè)簡單下載網(wǎng)頁的例子,然后將其擴(kuò)展為可以下載任何文件。 環(huán)境:Windows Xp + Qt 4.8.5+Qt Creator 2.8.0 目錄 一、簡單的網(wǎng)頁瀏覽功能 二、實(shí)現(xiàn)下載文件功能 正文 一、簡單的網(wǎng)頁瀏覽功能 1.新建Qt Gui應(yīng)用,項(xiàng)目名稱為http,基類使用默認(rèn)的QMainWindow即可,類名為MainWindow。 2.完成后打開http.pro文件,然后添加下面一行代碼來使用網(wǎng)絡(luò)模塊: QT??+=?network ? ?? ??然后保存該文件。 3.下面打開mainwindow.ui文件進(jìn)入設(shè)計(jì)模式,向界面上添加一個(gè)Text Browser部件。效果如下圖所示。 4.打開mainwindow.h文件,先包含頭文件:#include <QtNetwork> 然后添加一個(gè)private私有對(duì)象定義:QNetworkAccessManager *manager; 最后添加一個(gè)私有槽聲明: private slots: void replyFinished(QNetworkReply *); 5.下面到mainwindow.cpp文件中,先在構(gòu)造函數(shù)中添加如下代碼: manager = new QNetworkAccessManager(this); connect(manager, SIGNAL(finished(QNetworkReply*)), this,SLOT(replyFinished(QNetworkReply*))); manager->get(QNetworkRequest(QUrl("http://www.qter.org"))); 這里先創(chuàng)建了一個(gè)QNetworkAccessManager類的實(shí)例,它用來發(fā)送網(wǎng)絡(luò)請(qǐng)求和接收應(yīng)答。然后關(guān)聯(lián)了管理器的finished()信號(hào)和我們自定義的槽,每當(dāng)網(wǎng)絡(luò)應(yīng)答結(jié)束時(shí)都會(huì)發(fā)射這個(gè)信號(hào)。最后使用了get()函數(shù)來發(fā)送一個(gè)網(wǎng)絡(luò)請(qǐng)求,網(wǎng)絡(luò)請(qǐng)求使用QNetworkRequest類表示,get()函數(shù)返回一個(gè)QNetworkReply對(duì)象。除了get()函數(shù),管理器還提供了發(fā)送HTTP POST請(qǐng)求的post()函數(shù)。 6.下面添加槽的定義: void MainWindow::replyFinished(QNetworkReply *reply) { QTextCodec *codec = QTextCodec::codecForName("utf8"); QString all = codec->toUnicode(reply->readAll()); ui->textBrowser->setText(all); reply->deleteLater(); } 因?yàn)?span style="font-family:Times New Roman; word-wrap:break-word">QNetworkReply繼承自QIODevice類,所以可以操作一般的I/O設(shè)備一樣來操作該類。這里使用了readAll()函數(shù)來讀取所有的應(yīng)答數(shù)據(jù),為了正常顯示中文,使用了QTextCodec類來轉(zhuǎn)換編碼。在完成數(shù)據(jù)的讀取后,需要使用deleteLater()來刪除replay對(duì)象。 7.因?yàn)檫@里使用了QtextCodec類,所以還需要在mainwindow.cpp文件中包含頭文件 #include <QTextCodec> ? ?? ??下面運(yùn)行程序,效果如下圖所示。 ? ?? ?? 這里再將整個(gè)過程簡答敘述一遍:上面實(shí)現(xiàn)了最簡單的應(yīng)用HTTP協(xié)議下載網(wǎng)頁的功能。QNetworkAccessManager類用于發(fā)送網(wǎng)絡(luò)請(qǐng)求和接受回復(fù),具體來說,它是用QNetworkRequest?類來管理請(qǐng)求,QNetworkReply類進(jìn)行接收回復(fù),并對(duì)數(shù)據(jù)進(jìn)行處理。 在上面的代碼中,我們使用了下面的代碼來發(fā)送請(qǐng)求: manager->get(QNetworkRequest(QUrl("http://www.qter.org"))); 它返回一個(gè)QNetworkReply對(duì)象,這個(gè)后面再講。我們只需知道只要發(fā)送請(qǐng)求成功,它就會(huì)下載數(shù)據(jù)。而當(dāng)數(shù)據(jù)下載完成后,manager會(huì)發(fā)出finished()信號(hào),我們關(guān)聯(lián)了該信號(hào): connect(manager, SIGNAL(finished(QNetworkReply*)), this,SLOT(replyFinished(QNetworkReply*))); 也就是說,當(dāng)下載數(shù)據(jù)結(jié)束時(shí),就會(huì)執(zhí)行replyFinished()函數(shù)。在這個(gè)函數(shù)中我們對(duì)接收的數(shù)據(jù)進(jìn)行處理: QTextCodec *codec = QTextCodec::codecForName("utf8"); QString all = codec->toUnicode(reply->readAll()); ui->textBrowser->setText(all); 這里,為了能顯示下載的網(wǎng)頁中的中文,我們使用了QTextCodec?類對(duì)象,應(yīng)用utf8編碼。使用reply->readAll()函數(shù)就可以將下載的所有數(shù)據(jù)讀出。然后,我們?cè)?span style="font-family:Times New Roman; word-wrap:break-word">textBrowser中將數(shù)據(jù)顯示出來。當(dāng)reply對(duì)象已經(jīng)完成了它的功能時(shí),我們需要將它釋放,就是最后一條代碼: reply->deleteLater(); 二、實(shí)現(xiàn)下載文件功能 ? ?? ?? 通過上面的例子可以看到,Qt中編寫基于HTTP協(xié)議的程序是十分簡單的,只有十幾行代碼。不過,一般我們下載文件都想要看到下載進(jìn)度。下面我們就更改上面的程序,讓它可以下載任意的文件,并且顯示下載進(jìn)度。 1.進(jìn)入設(shè)計(jì)模式,刪除以前的Text Browser部件,然后拖入一個(gè)Line Edit,一個(gè)Label,一個(gè)Progress Bar和一個(gè)Push Button,設(shè)計(jì)界面如下圖所示。 2.?在寫代碼之前,我們先介紹一下整個(gè)程序執(zhí)行的流程:開始我們先讓進(jìn)度條隱藏。當(dāng)我們?cè)?span style="font-family:Times New Roman; word-wrap:break-word">Line Edit中輸入下載地址,點(diǎn)擊下載按鈕后,我們應(yīng)用輸入的下載地址,獲得文件名,在磁盤上新建一個(gè)文件,用于保存下載的數(shù)據(jù),然后進(jìn)行鏈接,并顯示進(jìn)度條。在下載過程中,我們將每次獲得的數(shù)據(jù)都寫入文件中,并更新進(jìn)度條,在接收完文件后,我們重新隱藏進(jìn)度條,并做一些清理工作。根據(jù)這個(gè)思路,我們開始代碼的編寫。 3.到mainwindow.h中,首先添加public函數(shù)聲明: void startRequest(QUrl?url);?//請(qǐng)求鏈接 然后添加幾個(gè)private變量和對(duì)象定義: QNetworkReply *reply; QUrl url;? ?//存儲(chǔ)網(wǎng)絡(luò)地址 QFile *file;??//文件指針 最后到private slots中,刪除前面的replyFinished(QNetworkReply *)槽聲明,并添加如下代碼: private slots: void on_pushButton_clicked();??//下載按鈕的單擊事件槽函數(shù) void httpFinished();??//完成下載后的處理 void httpReadyRead();??//接收到數(shù)據(jù)時(shí)的處理 void updateDataReadProgress(qint64, qint64); //更新進(jìn)度條 4.?下面到mainwindow.cpp文件中,將前面在構(gòu)造函數(shù)中添加的內(nèi)容刪除,然后添加如下代碼: manager = new QNetworkAccessManager(this);?? ui->progressBar->hide(); 我們?cè)跇?gòu)造函數(shù)中先隱藏進(jìn)度條。等開始下載時(shí)再顯示它。 5.?下面將前面程序中添加的replyFinished()函數(shù)的定義刪除,然后添加新的函數(shù)的定義。先添加網(wǎng)絡(luò)請(qǐng)求函數(shù)的實(shí)現(xiàn): void MainWindow::startRequest(QUrl url) { reply = manager->get(QNetworkRequest(url)); connect(reply, SIGNAL(readyRead()),?this, SLOT(httpReadyRead())); connect(reply, SIGNAL(downloadProgress(qint64, qint64)), this, SLOT(updateDataReadProgress(qint64, qint64))); connect(reply, SIGNAL(finished()),?this, SLOT(httpFinished())); } 這里使用了get()函數(shù)來發(fā)送網(wǎng)絡(luò)請(qǐng)求,然后進(jìn)行了QNetworkReply對(duì)象的幾個(gè)信號(hào)和自定義槽的關(guān)聯(lián)。其中readyRead()信號(hào)繼承自QIODevice類,每當(dāng)有新的數(shù)據(jù)可以讀取時(shí),都會(huì)發(fā)射該信號(hào);每當(dāng)網(wǎng)絡(luò)請(qǐng)求的下載進(jìn)度更新時(shí)都會(huì)發(fā)射downloadProgress()信號(hào),它用來更新進(jìn)度條;每當(dāng)應(yīng)答處理結(jié)束時(shí),都會(huì)發(fā)射finished()信號(hào),該信號(hào)與前面程序中QNetworkAccessManager類的finished()信號(hào)作用相同,只不過是發(fā)送者不同,參數(shù)也不同而已。下面添加幾個(gè)槽的定義。 void MainWindow::httpReadyRead() { if (file) file->write(reply->readAll()); } 這里先判斷是否創(chuàng)建了文件,如果是,則讀取返回的所有數(shù)據(jù),然后寫入到文件。該文件是在后面的“下載”按鈕單擊信號(hào)槽中創(chuàng)建并打開的。 void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes) { ui->progressBar->setMaximum(totalBytes); ui->progressBar->setValue(bytesRead); } ? ?? ??? 這里設(shè)置了一下進(jìn)度條的最大值和當(dāng)前值。 void MainWindow::httpFinished() { ui->progressBar->hide(); file->flush(); file->close(); reply->deleteLater(); reply = 0; delete file; file = 0; } ? ?? ??? 當(dāng)完成下載后,重新隱藏進(jìn)度條,然后刪除reply和file對(duì)象。下面是“下載”按鈕的單擊信號(hào)的槽: void MainWindow::on_pushButton_clicked() { url = ui->lineEdit->text(); QFileInfo info(url.path()); QString fileName(info.fileName()); if (fileName.isEmpty()) fileName = "index.html"; file = new QFile(fileName); if(!file->open(QIODevice::WriteOnly)) { qDebug() << "file open error"; delete file; file = 0; return; } startRequest(url); ui->progressBar->setValue(0); ui->progressBar->show(); } 這里使用要下載的文件名創(chuàng)建了本地文件,然后使用輸入的url進(jìn)行了網(wǎng)絡(luò)請(qǐng)求,并顯示進(jìn)度條。 6.下面運(yùn)行程序,我們先輸入www.yafeilinux.com的網(wǎng)址,下面一個(gè)網(wǎng)頁。效果如下圖所示。 ? 完成后,可以嘗試輸入一個(gè)文件的下載地址,比如這里輸入了《Qt Creator快速入門》一書在百度網(wǎng)盤上的地址,效果如下圖所示。 7.最后,可以去項(xiàng)目編譯生成的文件目錄中查看下載的文件(我這里是E:\http-build-桌面-Debug),可以看到下載的文件,如下圖所示。 結(jié)語 HTTP應(yīng)用的內(nèi)容就講到這里,可以看到它是很容易的,也不需要大家了解太多的HTTP的原理知識(shí)。關(guān)于相關(guān)的類的其他使用,也可以查看其幫助文檔。在上面的例子中,我們只是為了講解知識(shí),所以程序不是很完善,對(duì)于一個(gè)真正的工程,還是需要注意更多其他細(xì)節(jié)的,大家可以查看一下Qt演示程序HTTP Client的源代碼。 涉及到的源碼:??http.zip?? |
總結(jié)
以上是生活随笔為你收集整理的[Qt教程] 第32篇 网络(二)HTTP的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [Qt教程] 第31篇 网络(一)Qt网
- 下一篇: [Qt教程] 第33篇 网络(三)FTP