網路編程目錄
*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伺服器,在每一個活動的用戶端只有一個線程。