天天看點

Qt網絡程式設計之一

網絡程式設計目錄

*Qt中有關網絡程式設計的類

*HTTP和FTP高層網絡操作

*使用QTcpSocket和QTcpServer進行TCP程式設計

*使用QUdpSocket進行UDP程式設計

*使用QHostInfo解析主機名

*對于網絡代理的支援

*Bearer Management Support

網絡程式設計

    QtNetwork子產品提供了我們實作TCP/IP用戶端和伺服器端的類。它提供了諸如實作特定應用層協定的QFtp類,代表底層網絡協定的類:QTcpSocket、QTcpServer和QUdpSocket,以及使用普遍協定進行網絡操作的高層次類:QNetworkRequest、QNetworkReply和QNetworkAccessManager。它同樣提供了用于實作bearer management的類:QNetworkConfigure、QNetworkConfigureManager和QNetworkSession。

Qt中用于網絡程式設計的類

下面的類用于支援Qt的網絡程式設計

關于HTTP和FTP的高層網絡操作

       Network Access API是常見網絡操作類的集合。該API對使用的特定操作和協定(例如:在HHTP上擷取和上傳資料),并且僅僅暴露一般的類、函數和信号或是高層次的概念。

       網絡請求是由QNetworkRequest類呈現的,該類也作為一個包含于請求相關資訊的容器,例如:任何頭部資訊和

使用的加密方式。在一個請求對象被建立的時候,指定的URL就可用來決定該請求所使用的協定。目前對于HHTP、FTP和本地檔案的URL都支援下載下傳和上傳。

       網絡操作的協同工作是由QNetworkAccessManagement類實作的。一旦一個請求被建立,該類就用來分發請求和發送信号報告請求處理的進度。manager同樣也用來協同在用戶端使用cookies存儲資料、授權請求和代理的使用。

       網絡請求的應答是由QNetworkReply類來呈現的,當一個請求被分發後它就會由QnetworkAccessManager建立。

QNetworkReply提供的信号可以被用來單獨的檢測每一個應答,或者開發者也可以選擇使用manager的信号來達到這種目的,而放棄使用查詢應答資訊的方式。由于QNetworkReply是QIODevice的子類,應答資訊可以被同步或者異步處理;例如阻塞或者非阻塞操作。

    每一個應用或庫都可以建立一個或者多個QNetworkAccessManager執行個體來處理網絡通信。

使用QFtp寫FTP用戶端

        FTP(檔案傳輸協定)是一種通常被使用來浏覽遠端主機目錄和檔案傳輸的協定。

FTP使用兩個網絡連接配接,一個用于傳輸指令一個用于傳輸資料。FTP協定有一個狀态,需要用戶端在傳輸資料之前發送幾個指令。FTP用戶端建立一個連接配接,并且通過會話保持該連接配接一直被打開。在每一路會話中可以發生多個傳輸操作。

        QFtp類提供對FTP協定用戶端的支援。它有如下特性:

*非阻塞操作。QFtp是異步的。你可以排程一系列的指令使某一個指令在控制權傳回到Qt的事件處理循環後再執行。

*指令ID。每一個指令都有一個唯一的ID,你可以使用該ID跟蹤該指令的執行情況。例如:QFtp針對每一個執行的命    令使用指令ID發送commandStarted()和commandFinished()信号。

*資料傳輸的進度訓示。無論處在資料發送的什麼階段,QFtp都發送信号(QFtp::dataTransferProgress(), 

  QNetworkReply::downloadProgress(), and QNetworkReply::uploadProgress())。你可以連接配接這些信号到

  QProgressBar::setProgress() 或者 QProgressDialog::setProgress()。

*QIODevice支援。該類提供了從QIODevice上下載下傳和上傳資料的支援,額外的基于QByteArray的API。

       這裡有兩種主要使用QFtp的方式。最常用的方法就是保持跟蹤指令ID,并且通過連接配接到合适的信号獲知每個

指令的執行情況。另外一種方法就是一次排程所有的指令,并且僅僅連接配接到done()信号,該信号在所有排程的

指令都執行完後才發送。第一種方式需要做更多的工作,但是它給予你對每個指令的執行更大的控制權,并且

允許你依據前一個指令的執行執行結果來初始化後面的指令。該方式也允許你提供更多的回報資訊給使用者。

       FTP示例展示了如何編寫一個FTP用戶端。依據低層次的類QTcpSocket和QTcpServer編寫你自己的FTP(或者HTTP)伺服器也是有可能的。

使用QTcpSocket和QTcpServer進行TCP程式設計

       TCP(傳輸控制協定)是被大多數英特網協定(包括HTTP和FTP)使用的底層網絡協定,主要用于資料傳輸。它是可靠的,面向流和面向連接配接的傳輸協定。它特别适合于連續的資料傳輸。

       QTcpSocket提供了一個TCP的接口。你可以使用QTcpSocket實作标準的網絡協定,例如:POP3、SMTP和NNTP以及自定義協定。

      在資料傳輸之前,必須建立一個到遠端主機和端口的TCP連接配接。一旦該連接配接建立了,那麼IP位址和端口号都可以通過QTcpSocket::peerAddress() 和 QTcpSocket::peerPort()擷取。任何時候都可以關閉連接配接,并且資料傳輸也會立即停止。

       QTcpSocket以異步的方式工作,并且通過發送信号報告狀态變化和錯誤,這一點和QNetworkAccessManager以及QFtp類似。它依賴于事件循環檢測到來的資料,并且自動重新整理即将發出去的資料。你可以通過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()來阻塞該程序,知道connected()信号被發送。

       同步的套接字通常使得代碼有一個非常簡單的控制流程。waitFor...()方法最大的弊端就是在waitFor...()函數阻塞的時候事件将得不到處理。如果在GUI線程中使用将導緻使用者界面當機。基于這個原因,我們建議你隻在非GUI線程中使用同步套接字。當使用同步套接字時,QTcpSocket不需要任何一個事件循環。

       Fortune Client 和 Fortune Server兩個示例展示了如何使用QTcpSocket和QTcpServer來編寫基于TCP用戶端-伺服器的應用程式。也可以檢視 Blocking Fortune Client示例來學習如何在一個單獨的線程中使用同步QTcpSocket(此時沒有使用事件循環),Threaded Fortune Server是一個多線程的TCP伺服器,在每一個活動的用戶端隻有一個線程。