天天看點

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

<a target="_blank" href="http://bbs.qter.org/forum.php?mod=viewthread&amp;tid=577">樓主</a>

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

 發表于 2013-8-28 17:21:28 | 檢視:

637| 回複: 8

http

版權聲明

該文章原創于作者yafeilinux,轉載請注明出處!

導語

http(hypertext transfer protocol,超文本傳輸協定)是一個用戶端和伺服器端請求和應答的标準。在qt的網絡子產品中提供了網絡通路接口來實作http程式設計。網絡通路接口是執行一般的網絡操作的類的集合,該接口在特定的操作和使用的協定(例如,通過http進行擷取和發送資料)上提供了一個抽象層,隻為外部暴露出了類、函數和信号。

上一節中我們已經提到過了,現在qt中使用qnetworkaccessmanager類和qnetworkreply類來進行http的程式設計。網絡請求由qnetworkrequest類來表示,它也作為與請求有關的資訊(例如,任何頭資訊和使用加密)的容器。在建立請求對象時指定的url決定了請求使用的協定,目前支援http、ftp和本地檔案urls的上傳和下載下傳。qnetworkaccessmanager類用來協調網絡操作,每當一個請求建立後,該類用來排程它,并發射信号來報告進度。該類還協調cookies的使用,身份驗證請求,及其代理的使用等。對于網絡請求的應答使用qnetworkreply類表示,它會在請求被完成排程時由qnetworkaccessmanager來建立。qnetworkreply提供的信号可以用來單獨的監視每一個應答。

       下面我們先講解一個簡單下載下傳網頁的例子,然後将其擴充為可以下載下傳任何檔案。

環境:windows xp + qt 4.8.5+qt creator 2.8.0

目錄

一、簡單的網頁浏覽功能

二、實作下載下傳檔案功能

正文

1.建立qt gui應用,項目名稱為http,基類使用預設的qmainwindow即可,類名為mainwindow。

2.完成後打開http.pro檔案,然後添加下面一行代碼來使用網絡子產品:

qt  += network

       然後儲存該檔案。

3.下面打開mainwindow.ui檔案進入設計模式,向界面上添加一個text browser部件。效果如下圖所示。

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

4.打開mainwindow.h檔案,先包含頭檔案:#include &lt;qtnetwork&gt;

然後添加一個private私有對象定義:qnetworkaccessmanager

*manager;

最後添加一個私有槽聲明:

private slots:

    void replyfinished(qnetworkreply *);

5.下面到mainwindow.cpp檔案中,先在構造函數中添加如下代碼:

manager = new qnetworkaccessmanager(this);

connect(manager, signal(finished(qnetworkreply*)),

this,slot(replyfinished(qnetworkreply*)));

manager-&gt;get(qnetworkrequest(qurl("http://www.qter.org")));

這裡先建立了一個qnetworkaccessmanager類的執行個體,它用來發送網絡請求和接收應答。然後關聯了管理器的finished()信号和我們自定義的槽,每當網絡應答結束時都會發射這個信号。最後使用了get()函數來發送一個網絡請求,網絡請求使用qnetworkrequest類表示,get()函數傳回一個qnetworkreply對象。除了get()函數,管理器還提供了發送http

post請求的post()函數。

6.下面添加槽的定義:

void mainwindow::replyfinished(qnetworkreply *reply)

{

    qtextcodec *codec = qtextcodec::codecforname("utf8");

    qstring all = codec-&gt;tounicode(reply-&gt;readall());

    ui-&gt;textbrowser-&gt;settext(all);

    reply-&gt;deletelater();

}

因為qnetworkreply繼承自qiodevice類,是以可以操作一般的i/o裝置一樣來操作該類。這裡使用了readall()函數來讀取所有的應答資料,為了正常顯示中文,使用了qtextcodec類來轉換編碼。在完成資料的讀取後,需要使用deletelater()來删除replay對象。

7.因為這裡使用了qtextcodec類,是以還需要在mainwindow.cpp檔案中包含頭檔案

#include &lt;qtextcodec&gt;

       下面運作程式,效果如下圖所示。

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

這裡再将整個過程簡答叙述一遍:上面實作了最簡單的應用http協定下載下傳網頁的功能。qnetworkaccessmanager類用于發送網絡請求和接受回複,具體來說,它是用qnetworkrequest 類來管理請求,qnetworkreply類進行接收回複,并對資料進行處理。

在上面的代碼中,我們使用了下面的代碼來發送請求:

它傳回一個qnetworkreply對象,這個後面再講。我們隻需知道隻要發送請求成功,它就會下載下傳資料。而當資料下載下傳完成後,manager會發出finished()信号,我們關聯了該信号:

也就是說,當下載下傳資料結束時,就會執行replyfinished()函數。在這個函數中我們對接收的資料進行處理:

qtextcodec *codec = qtextcodec::codecforname("utf8");

qstring all = codec-&gt;tounicode(reply-&gt;readall());

ui-&gt;textbrowser-&gt;settext(all);

這裡,為了能顯示下載下傳的網頁中的中文,我們使用了qtextcodec 類對象,應用utf8編碼。使用reply-&gt;readall()函數就可以将下載下傳的所有資料讀出。然後,我們在textbrowser中将資料顯示出來。當reply對象已經完成了它的功能時,我們需要将它釋放,就是最後一條代碼:

reply-&gt;deletelater();

通過上面的例子可以看到,qt中編寫基于http協定的程式是十分簡單的,隻有十幾行代碼。不過,一般我們下載下傳檔案都想要看到下載下傳進度。下面我們就更改上面的程式,讓它可以下載下傳任意的檔案,并且顯示下載下傳進度。

1.進入設計模式,删除以前的text browser部件,然後拖入一個line edit,一個label,一個progress

bar和一個push button,設計界面如下圖所示。

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

2. 在寫代碼之前,我們先介紹一下整個程式執行的流程:開始我們先讓進度條隐藏。當我們在line edit中輸入下載下傳位址,點選下載下傳按鈕後,我們應用輸入的下載下傳位址,獲得檔案名,在磁盤上建立一個檔案,用于儲存下載下傳的資料,然後進行連結,并顯示進度條。在下載下傳過程中,我們将每次獲得的資料都寫入檔案中,并更新進度條,在接收完檔案後,我們重新隐藏進度條,并做一些清理工作。根據這個思路,我們開始代碼的編寫。

3.到mainwindow.h中,首先添加public函數聲明:

void startrequest(qurl url); //請求連結

然後添加幾個private變量和對象定義:

qnetworkreply *reply;

qurl url;   //存儲網絡位址

qfile *file;  //檔案指針

最後到private slots中,删除前面的replyfinished(qnetworkreply *)槽聲明,并添加如下代碼:

    void on_pushbutton_clicked();  //下載下傳按鈕的單擊事件槽函數

    void httpfinished();  //完成下載下傳後的處理

    void httpreadyread();  //接收到資料時的處理

    void updatedatareadprogress(qint64, qint64); //更新進度條

4. 下面到mainwindow.cpp檔案中,将前面在構造函數中添加的内容删除,然後添加如下代碼:

manager = new qnetworkaccessmanager(this);  

ui-&gt;progressbar-&gt;hide();

我們在構造函數中先隐藏進度條。等開始下載下傳時再顯示它。

5. 下面将前面程式中添加的replyfinished()函數的定義删除,然後添加新的函數的定義。先添加網絡請求函數的實作:

void mainwindow::startrequest(qurl url)

    reply = manager-&gt;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()函數來發送網絡請求,然後進行了qnetworkreply對象的幾個信号和自定義槽的關聯。其中readyread()信号繼承自qiodevice類,每當有新的資料可以讀取時,都會發射該信号;每當網絡請求的下載下傳進度更新時都會發射downloadprogress()信号,它用來更新進度條;每當應答處理結束時,都會發射finished()信号,該信号與前面程式中qnetworkaccessmanager類的finished()信号作用相同,隻不過是發送者不同,參數也不同而已。下面添加幾個槽的定義。

void mainwindow::httpreadyread()

    if (file) file-&gt;write(reply-&gt;readall());

這裡先判斷是否建立了檔案,如果是,則讀取傳回的所有資料,然後寫入到檔案。該檔案是在後面的“下載下傳”按鈕單擊信号槽中建立并打開的。

void mainwindow::updatedatareadprogress(qint64 bytesread, qint64 totalbytes)

    ui-&gt;progressbar-&gt;setmaximum(totalbytes);

    ui-&gt;progressbar-&gt;setvalue(bytesread);

這裡設定了一下進度條的最大值和目前值。

void mainwindow::httpfinished()

    ui-&gt;progressbar-&gt;hide();

    file-&gt;flush();

    file-&gt;close();

    reply = 0;

    delete file;

    file = 0;

當完成下載下傳後,重新隐藏進度條,然後删除reply和file對象。下面是“下載下傳”按鈕的單擊信号的槽:

void mainwindow::on_pushbutton_clicked()

    url = ui-&gt;lineedit-&gt;text();

    qfileinfo info(url.path());

    qstring filename(info.filename());

    if (filename.isempty()) filename = "index.html";

    file = new qfile(filename);

    if(!file-&gt;open(qiodevice::writeonly))

    {

        qdebug() &lt;&lt; "file open error";

        delete file;

        file = 0;

        return;

    }

    startrequest(url);

    ui-&gt;progressbar-&gt;setvalue(0);

    ui-&gt;progressbar-&gt;show();

這裡使用要下載下傳的檔案名建立了本地檔案,然後使用輸入的url進行了網絡請求,并顯示進度條。

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

完成後,可以嘗試輸入一個檔案的下載下傳位址,比如這裡輸入了《qt creator快速入門》一書在百度網盤上的位址,效果如下圖所示。

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

7.最後,可以去項目編譯生成的檔案目錄中檢視下載下傳的檔案(我這裡是e:\http-build-桌面-debug),可以看到下載下傳的檔案,如下圖所示。

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

結語

http應用的内容就講到這裡,可以看到它是很容易的,也不需要大家了解太多的http的原理知識。關于相關的類的其他使用,也可以檢視其幫助文檔。在上面的例子中,我們隻是為了講解知識,是以程式不是很完善,對于一個真正的工程,還是需要注意更多其他細節的,大家可以檢視一下qt示範程式http

client的源代碼。

涉及到的源碼: 

[Qt教程] 第32篇 網絡(二)HTTP [Qt教程] 第32篇 網絡(二)HTTP

kb, 下載下傳次數: 14)