分类: 嵌入式
2013-07-24 17:15:05
Qt包含了各式各样的模组供使用者使用与开发应用程式,而在网路程式设计的部分,就是由QtNetwork module来提供了各式各样的类别供程式设计师撰写TCP/IP为基础的网路应用程式,让程式设计师使用上更简单、容易移植。
QtNetwork module所提供的函式库包括了基本的HTTP与FTP应用层通讯协定的QHttp和QFtp,经由网路来下载或上传档案更加简单快速。
除了上层通讯协定之外,也包含了底层网路类别,包括了QTcpSocket与QUdpSocket,这些类别分别实做了TCP与UDP这两个传输层通讯协定,而在底层之上则包括有QnetworkRequest、QNetworkReply以及QNetworkAccessmanager, 利用一般的通讯协定来进行网路功能的运作。
QtNetwork module目前是属于Full Framework Edition与Open Souce Versions的一部份,Qt各版本的不同请参考。
在本篇将会介绍如何在Qt利用上述通讯协定来撰写程式。
若要撰写使用Qt网路功能的应用程式,势必会使用到Qt的那些网路类别,则必须在build的时候设定将QtNetwork模组加入。
简单来讲,其实只需要在qmake –project之后产生的project档(xxx.pro)加入下列的指令即可;如此一来,在qmake编译时,看到这行指令就会正确地连结(link)到QtNetwork函式库:
QT += network
至于为何需要此步骤呢?
由于Qt预设只会载入QtCore与QtGui这两个基本的模组,因此要使用其他模组就一定要加入此行指令(往后若有使用到其他模组,则可依此类推)。而在程式中要使用到QtNetwork module的类别时,只需要用下列指令加入即可:
#include
知道如何撰写Qt Network程式的首要步骤之后,接着就是要撰写一个简单的程式做练习;而我们的第一支Qt网路程式就是利用QHttp和QFtp写一个简单的HTTP和FTP client。
HTTP(Hypertext Transfer Protocol)是应用层(application-level)的网路通讯协定,可用于下载HTML与XML档案,亦可使用于高阶传输的通讯协定,包括其他类型的资料传输等。而FTP(File Transfer Protocol)则几乎专用于浏览远端目录以及传输档案。
QHttp提供了基本HTTP的功能,包括get()和post(),并且提供了各种方法来送HTTP request,而要撰写一个简单的HTTP程式其实不难,基本上只需要先了解如何使用下列QHttp的函式即可。
1、首先是设定HTTP伺服器的hostName与port:
int QHttp:: setHost ( const QString & hostName, quint16 port = 80 )
此函式的运作是非同步(实际上,所有QHttp的运作皆是如此),并且会由requestStarted( )和requestFinished( )回传一个单一的识别。
2、设定要下载的档案(get请求给setHost()中设定的hostName以及路径):
int QHttp:: get ( const QString & path, QIODevice * to = 0 )
path必须是一个绝对路径(eg, /index.html)或绝对URI(
3、结束连线,常用于关闭一个keep-alive的连线(刚提到的get( )所送出的请求皆会被QHttp设定为keep-alive 连线):
int QHttp:: close ( )
基本上只要使用到上述的函式即可建立连线并且下载档案,就是一个很简易的Http客户端了,
皆下来范例程式,在命令列模式下利用HTTP get来下载指定的档案:
#include#include #include #include #include using namespace std; int main ( int argc, char * argv [ ] ) { QCoreApplication app ( argc, argv ) ; QFile * file ; QHttp *http = new QHttp ( ) ; QUrl url ( "" ) ; QFileInfo fileInfo ( url. path ( ) ) ; QString fileName = fileInfo. fileName ( ) ; file = new QFile ( fileName ) ; if ( !file->open ( QIODevice:: WriteOnly ) ) { cerr << "Unable to save the file" << endl; delete file ; file = 0 ; } http ->setHost ( url. host ( ) , url. port ( 80 ) ) ; http->get ( url. path ( ) , file ) ; http->close ( ) ; return app. exec ( ) ; }
上述的范例是不是很浅显易懂呢?以下有几个部分特别说明一下:
QFtp提供FTP通讯协定的实做,包括interface让使用者直接使用来控制其中的request。这个类别的运作是非同步的,因此如果函式无法立即执行,则执行动作将会排程稍后再执行。而所有执行动作的结果都会经由signal回报,能够被排程的指令包括connectToHost()、 login()、close(),、list()、cd()、get()、put()、remove() 、mkdir()、rmdir()、 rename()和rawCommand()。
所有的指令都会回传一个单一的识别值(identifier),以方便追踪指令是否被执行。当某个指令开始执行时,会发送commandStarted() signal,并且伴随着那个指令的识别值(identifier);而当指令结束时,commandFinished() signal会发送并伴随着指令的识别值,并且还有一个bool值说明指令是否有发生错误。
以下撷取出连线到FTP伺服器的部分程式码:
QFtp *ftp = new QFtp ( ) ; ftp->connectToHost ( "ftp.isu.edu.tw/" ) ; ftp->login ( ) ;
以下是一个简单的范例程式,利用FTP通讯协定到指定的位址下载档案。范例档案与上力的HTTP类似,因此我将只列出实际执行下载档案的程式内容:
ftp->setTransferMode ( QFtp:: Passive ) ; ftp->connectToHost ( “ftp. isu . edu . tw ” ) ; ftp->login ( ) ; ftp->cd ( "pub" ) ; ftp->get ( " 00_index.txt" ) ; ftp->close ( ) ;
上面的程式码片段是利用FTP连接至ftp.isu.edu.tw,并且是Passive Mode连线(预设)。
connectToHost( )中若未指定port,则为预设的21。
cd( )将进入指定的位置,而get( )则指定要下载的档案。
最后close()结束连线。
以下是一个简易的范例程式,而与前一个范例不同的是,这个范例将会使用到.h表头档,所以档案会比较多。
首先,请看FtpGet.h:
#ifndef FTPGET_H #define FTPGET_H #includeclass QUrl; class QFtp; class QFile; class FtpGet : public QObject { Q_OBJECT public : FtpGet ( QObject *parent = 0 ) ; void downloadFile ( const QUrl &url ) ; signals: void finished ( ) ; private slots: void done ( bool error ) ; private : QFtp *ftp; QFile * file ; } ; #endif
上述档案有几个需要注意的部分:
再来请看实做类别的FtpGet.cpp:
#include#include #include #include "FtpGet.h" using namespace std; FtpGet:: FtpGet ( QObject *parent ) : QObject ( parent ) { ftp = new QFtp ( this ) ; connect ( ftp, SIGNAL ( done ( bool ) ) , this , SLOT ( done ( bool ) ) ) ; } void FtpGet:: downloadFile ( const QUrl &url ) { QFileInfo fileInfo ( url. path ( ) ) ; QString fileName = fileInfo. fileName ( ) ; file = new QFile ( fileName ) ; if ( !file->open ( QIODevice:: WriteOnly ) ) { cerr << "Unable to save the file" << endl; delete file ; file = 0 ; return ; } ftp->setTransferMode ( QFtp:: Passive ) ; ftp->connectToHost ( url. host ( ) , url. port ( 21 ) ) ; ftp->login ( ) ; ftp->get ( url. path ( ) , file ) ; ftp->close ( ) ; } void FtpGet:: done ( bool error ) { if ( error ) { cerr << "Error: " << qPrintable ( ftp->errorString ( ) ) << endl; } else { cerr << "File downloaded as " << qPrintable ( file->fileName ( ) ) << endl; } file->close ( ) ; delete file ; file = 0 ; emit finished ( ) ; }
上述档案有几个需要注意的部分:
最后就是main.cpp的部分:
#include#include #include "FtpGet.h" #include using namespace std; int main ( int argc, char *argv [ ] ) { QCoreApplication app ( argc, argv ) ; FtpGet getter; getter. downloadFile ( QUrl ( "ftp://ftp.isu.edu.tw/00_index.txt" ) ) ; QObject:: connect ( &getter, SIGNAL ( finished ( ) ) , &app, SLOT ( quit ( ) ) ) ; return app. exec ( ) ; }
这部分就很简单啰,请自行看吧。
原文链接: