Qt网络编程
Qt網絡編程之一
http://blog.csdn.net/chenlong12580/article/details/7434114
網絡編程目錄
*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服務器,在每一個活動的客戶端只有一個線程。
使用QUdpSocket進行UDP編程
? ? ? ?QUdpSocket類允許你發送和接收UDP數據報。它繼承自QAbstractSocket,因此它有共享了QTcpSocket的大多數接口。最主要的不同就是QUdpSocket以數據報的形式發送數據,而不像QTcpSocket使用連續的數據流。簡言之,一個數據報就是一個有大小限制數據包(通常小于512bytes),包含發送方的IP地址和端口號、接收方的IP地址和端口號以及要傳輸的數據。
? ? ? ?QUdpSocket支持IPv4廣播。廣播通常是用于實現網絡發現協議,例如尋找網絡上擁有最大空余磁盤空間的主機。一個主機發出的數據報,網絡上的其它主機都可以接收到。每一個主機都接收到一個請求,然后返回一個應答信息給發送者,表明當前可用磁盤空間。發廣播的主機直到接收到所有其它主機的應答信息才從中選擇可用磁盤空間最大的主機來存儲數據。要廣播一個數據報,僅僅只需要將該數據報發送給特殊的地址:QHostAddress::Broadcast (255.255.255.255),或者是你本地網絡的廣播地址。
? ? ? ?QUdpSocket::bind()創建用于接收進入的數據報,這個和TCP服務器的 QTcpServer::listen()十分相似。無論什么時候當一個或者多個數據報到達時,QUdpSocket就會發送readyRead()信號。調用QUdpSocket::readDatagram()來讀取數據報。
? ? ? ?Broadcast Sender 和 Broadcast Receiver示例展示了如何使用Qt編寫UDP發送者和UDP接收者。
? ? ? ?QUdpSocket同樣支持多播。Multicast Sender 和 Multicast Receiver示例展示了如何編寫UDP多播客戶端。
使用QHostInfo解析主機名稱
? ? ? ?在建立網絡連接之前,QTcpSocket和QUdpSocket進行一個名稱查詢,將你連接的主機的名稱翻譯為一個IP地址。這個操作通常都是使用DNS(域名服務)協議。
? ? ? ?QHostInfo提供了一個靜態的方法,使得你可以自己完成這個查詢操作。提供使用一個主機名、一個QObject指針和一個槽函數作為參數調用QHostInfo::lookupHost(),QHostInfo將會執行名稱查詢,并且在查詢結束的時候調用已經指定的槽函數。實際的查詢操作將會在一個單獨的線程中完成,利用操作系統自己的方法進行名稱查詢操作。
? ? ? ?QHostInfo也提供了一個稱為QHostInfo::fromName()的靜態方法,該方法將主機名作為參數和返回的結果。在這種情況下,查詢操作與函數調用者在一個線程中完成。這個重載對于非GUI應用或將查詢操作放在一個單獨的,非GUI的線程中是十分有用的。(在一個GUI線程中調用這個函數可能會在它執行查詢操作的時候導致你的UI凍結。)
支持網絡代理
? ? ? ?使用Qt進行網絡通信可以通過代理完成,也就是在本地和遠程的連接中指向或者過濾網絡路徑。
? ? ? ?單個的代理是由QNetworkProxy類呈現的,該類用來描述和配置到代理的接連。不同層次的網絡通信代理類型都得到了支持,由于SOCKS 5的支持,使得允許在一個低層次的網絡流量使用代理,HTTP和FTP代理工作在協議層次。查看QNetworkProxy::ProxyType獲取更多的信息。
? ? ? ?代理可以在一個應用程序的單個套接字或者全部網絡通信上使能。一個新打開的套接字在它被連接之前可以通過調用QAbstractSocket::setProxy()函數來使用代理。應用程序范圍的代理可以通過調用QNetworkProxy::setApplicationProxy()函數對所有的套接字連接使能的。
? ? ? ?代理工廠主要用于創建代理使用的策略。QNetworkProxyFactory是通過基于查詢具體代理類型來支持代理的。 查詢本身是使用QNetworkProxyQuery對象來編碼的,該對象以基于關鍵的標準來選擇使能的代理,,例如,代理的目的(TCP,UDP連接,TCP服務器,URL請求),本地的端口,遠程主機和端口,使用的協議(HTTP,FTP等)。
QNetworkProxyFactory::proxyForQuery()被用來直接的查詢工廠。一個應用程序范圍的代理的策略可以通過傳遞一個factory給QNetworkProxyFactory::setApplicationProxyFactory()來實現,并且自定義的程序級代理策略可以通過創建QNetworkProxyFactor的子類實現,查看相應的類文檔獲取詳細信息。
Bearer Management支持
? ? ? ?Bearer Management控制著設備的連接狀態,例如:應用程序可以啟動和停止網絡接口,并且在接入點之間透明的漫游。
? ? ? ?QNetworkConfigurationManager類管理者設備所知的一系列網絡配置。一個網絡配置描述了啟動網絡接口的參數集合,并且使用QNetworkConfiguration類代表。
? ? ? ?一個網絡接口通過給定的網絡配置打開一個QNetworkSession來完成啟動。大多數情況下,基于特定平臺默認的網絡配置創建網絡會話是合適的。默認的網絡配置是函數QNetworkConfigurationManager::defaultConfiguration()返回的。
? ? ? ?在一些平臺上,平臺要求應用程序在進行任何網絡操作之前打開一個網絡會話。這個可以通過
QNetworkConfigurationManager::capabilities()函數返回QNetworkConfigurationManager::NetworkSessionRequired
的值來測試。
總結
- 上一篇: 完整asp.net图形验证码程序
- 下一篇: React开发(239):dva概念4d