Qt應(yīng)用程序開發(fā)8_第1頁
Qt應(yīng)用程序開發(fā)8_第2頁
Qt應(yīng)用程序開發(fā)8_第3頁
Qt應(yīng)用程序開發(fā)8_第4頁
Qt應(yīng)用程序開發(fā)8_第5頁
已閱讀5頁,還剩51頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

Qt應(yīng)用程序開發(fā)Qt4程序設(shè)計根底QtDesigner應(yīng)用QMainWindow、QDialog、LayoutQt4數(shù)據(jù)庫應(yīng)用Qt4多線程應(yīng)用Qt4定時器Qt4事件處理Qt4網(wǎng)絡(luò)編程QSS樣式設(shè)計QGraphicsView應(yīng)用自定義控件Qt4網(wǎng)絡(luò)編程網(wǎng)絡(luò)模塊簡介HTTP編程

FTP編程獲取本機(jī)網(wǎng)絡(luò)信息

UDP編程TCP編程1網(wǎng)絡(luò)模塊簡介在Qt中提供了網(wǎng)絡(luò)模塊〔QtNetworkModule〕來用于網(wǎng)絡(luò)程序的開發(fā),在網(wǎng)絡(luò)模塊提供了多個相關(guān)類。用于FTP編程的QFtp類,用于HTTP編程的QNetworkAccessManager類和QNetworkReply類,用于獲得本機(jī)信息的QHostInfo類,用于Tcp編程的QTcpServer類和QTcpSocket類,用于UDP編程的QUdpSocket類,用于網(wǎng)絡(luò)加密的QSslSocket類,用于網(wǎng)絡(luò)代理的QNetworkProxy類等等。包含頭文件:#include<QtNetwork>在.pro文件中參加:QT+=network1網(wǎng)絡(luò)模塊簡介2HTTP編程?HTTP即超文本傳輸協(xié)議,它是一種文件傳輸協(xié)議。Qt中使用QNetworkAccessManager類和QNetworkReply類來進(jìn)行HTTP的編程??梢岳肏TTP從網(wǎng)站上下載文件。QNetworkAccessManager類實現(xiàn)應(yīng)用程序發(fā)送網(wǎng)絡(luò)請求和接收回應(yīng)的數(shù)據(jù)。實例化QNetworkAccessManager對象后,利用該對象發(fā)送網(wǎng)絡(luò)請求,每次的請求后都會返回一個QNetworkReply對象.這個對象能夠根據(jù)相應(yīng)的請求來獲得任何返回的數(shù)據(jù)。例如: QNetworkAccessManager*manager=newQNetworkAccessManager(this); connect(manager,SIGNAL(finished(QNetworkReply*)),this, SLOT(replyFinished(QNetworkReply*))); manager->")));QNetworkAccessManager有異步的API.如上例中當(dāng)replyFinished()插槽被調(diào)用時,附帶著QNetworkReply對象,同時包含著下載的數(shù)據(jù)等。2HTTP編程QNetworkAccessManager公有方法QNetworkReply

*QNetworkAccessManager::get(const

QNetworkRequest

&

request

)說明:發(fā)送一個請求來獲得請求的內(nèi)容,該方法返回一個QNetworkReply對象,并隨時讀取當(dāng)有新數(shù)據(jù)到達(dá)時所發(fā)射的readyRead()信號。請求的內(nèi)容及標(biāo)題就會被下載。QNetworkAccessManager信號voidQNetworkAccessManager::finished(

QNetworkReply

*

reply

)說明:只要發(fā)送請求成功,它就會下載數(shù)據(jù),而當(dāng)數(shù)據(jù)下載完成后,該信號就會被發(fā)射。注意:在request完成后,在適當(dāng)?shù)臅r候要刪除QNetworkReply對象,但是不要在與finished()信號相連接的插槽刪除該對象,可以利用deleteLater()方法來刪除。2HTTP編程注意:QNetworkAccessManager把接收到的所有request都放到一個隊列中.并行被執(zhí)行的request數(shù)目依賴于協(xié)議。目前HTTP協(xié)議在桌面平臺針對一個主機(jī)端口支持同時執(zhí)行6個request。例子:QNetworkRequestrequest;request.setUrl(QUrl(":"));request.setRawHeader("User-Agent","MyOwnBrowser1.0");QNetworkReply*reply=manager->get(request);connect(reply,SIGNAL(readyRead()),this,SLOT(slotReadyRead()));connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),this,SLOT(slotError(QNetworkReply::NetworkError)));connect(reply,SIGNAL(sslErrors(QList<QSslError>)),this,SLOT(slotSslErrors(QList<QSslError>)));2HTTP編程QNetworkReply類信號voidQIODevice::readyRead()

[signal]QNetworkReply類是由QIODevice類派生過來的。readyRead()信號是QIODevice類所有的,每次從設(shè)備讀取的新數(shù)據(jù)到達(dá)時,該信號就會被發(fā)射。當(dāng)有新數(shù)據(jù)追加到設(shè)備時,該信號會再次發(fā)射。而當(dāng)還有數(shù)據(jù)在緩沖區(qū)等待讀取的時候,該信號就不會被發(fā)射。voidQNetworkReply::error(

QNetworkReply::NetworkError

code

)

[signal]當(dāng)reply探測到在處理過程中有錯誤的時候,該信號就會被發(fā)射。同時finished()信號也會跟隨被發(fā)射,說明該請求連接結(jié)束。code參數(shù)指定錯誤的代碼,可以通過errorString()方法來獲取具體的錯誤信息。voidQNetworkReply::sslErrors(const

QList<QSslError>&

errors

)

[signal]在SSL/TLSsession建立時如果遇到錯誤,該信號就會被發(fā)射,如當(dāng)證書驗證錯誤等。Errors參數(shù)包含了錯誤的列表。2HTTP編程QNetworkReply類信號voidQNetworkReply::downloadProgress(

qint64

bytesReceived,

qint64

bytesTotal

)

[signal]該信號被發(fā)射來說明網(wǎng)絡(luò)請求數(shù)據(jù)下載的進(jìn)度。QNetworkReply類公有成員QByteArray

QIODevice::readAll()這是個重載的方法,從設(shè)備中讀取所有的下載數(shù)據(jù)。返回類型為QByteArray.當(dāng)QByteArray()為空時,說明設(shè)備中沒有可供讀取的數(shù)據(jù),或者在讀取過程中出現(xiàn)了錯誤。2HTTP編程-例子例子:實現(xiàn)簡單的應(yīng)用HTTP協(xié)議下載網(wǎng)頁的程序。QNetworkAccessManager類用于發(fā)送網(wǎng)絡(luò)請求和接收回復(fù),具體的是用QNetworkRequest類來管理請求,QNetworkReply類進(jìn)行接收回復(fù),并對數(shù)據(jù)進(jìn)行處理。參考代碼如下:2HTTP編程-例子Widget.h代碼如下:classWidget:publicQWidget{Q_OBJECTpublic:Widget(QWidget*parent=0);~Widget();protected:voidchangeEvent(QEvent*e);private:Ui::Widget*ui;

QNetworkAccessManager*manager;privateslots:

voidreplyFinished(QNetworkReply*);};2HTTP編程-例子Widget.cpp代碼如下:Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);this->manager=newQNetworkAccessManager(this);connect(this->manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replyFinished(QNetworkReply*)));this->manager->")));}voidWidget::replyFinished(QNetworkReply*reply){QTextCodec*codec=QTextCodec::codecForName("GB18030");QStringall=codec->toUnicode(reply->readAll());this->ui->textBrowser->setText(all);reply->deleteLater();}2HTTP編程-例子2功能:在上次例子的根底上,實現(xiàn)下載文件的功能,并能顯示下載進(jìn)度。2HTTP編程-例子2Widget.h代碼如下:classWidget:publicQWidget{Q_OBJECTpublic:Widget(QWidget*parent=0);~Widget();voidstartRequest(QUrlurl);//請求鏈接private:Ui::Widget*ui;QNetworkAccessManager*manager;QNetworkReply*reply;QUrlurl;//存儲網(wǎng)絡(luò)地址QFile*file;//文件指針privateslots:voidon_pushButton_clicked();//下載按鈕的單擊事件槽函數(shù)voidFinished();//完成下載后的處理voidReadyRead();//接收到數(shù)據(jù)時的處理voidupdateDataReadProgress(qint64,qint64);//更新進(jìn)度條};2HTTP編程-例子2Widget.cpp代碼如下:#include"widget.h"#include"ui_widget.h"#include"QFileInfo"#include"QDebug"#include"QNetworkRequest“Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);this->manager=newQNetworkAccessManager();this->ui->progressBar->hide();}2HTTP編程-例子2Widget.cpp代碼如下:voidWidget::on_pushButton_clicked(){url=ui->lineEdit->text();QFileInfoinfo(url.path());QStringfileName(info.fileName()); //獲取文件名if(fileName.isEmpty())fileName="index.html"; file=newQFile(fileName);if(!file->open(QIODevice::WriteOnly)){//如果翻開文件失敗,那么刪除file,并使file指針為0,然后返回qDebug()<<"fileopenerror";deletefile;file=0;return; }startRequest(url);//進(jìn)行鏈接請求ui->progressBar->setValue(0);//進(jìn)度條的值設(shè)為0ui->progressBar->show();//顯示進(jìn)度條}2HTTP編程-例子2Widget.cpp代碼如下:voidWidget::startRequest(QUrlurl){reply=manager->get(QNetworkRequest(url));//下面關(guān)聯(lián)信號和槽connect(reply,SIGNAL(finished()),this,SLOT(Finished()));//下載完成后connect(reply,SIGNAL(readyRead()),this,SLOT(ReadyRead()));//有可用數(shù)據(jù)時connect(reply,SIGNAL(downloadProgress(qint64,qint64)),this,SLOT(updateDataReadProgress(qint64,qint64)));//更新進(jìn)度條}voidWidget::ReadyRead(){if(file)file->write(reply->readAll());//如果文件存在,那么寫入文件}2HTTP編程-例子2Widget.cpp代碼如下:voidWidget::updateDataReadProgress(qint64bytesRead,qint64totalBytes){ui->progressBar->setMaximum(totalBytes);//最大值ui->progressBar->setValue(bytesRead);//當(dāng)前值}voidWidget::Finished(){ui->progressBar->hide();file->flush();file->close();this->reply->deleteLater();reply=0;deletefile;file=0;}3FTP編程?FTP即FileTransferProtocol,也就是文件傳輸協(xié)議。FTP的主要作用,就是讓用戶連接上一個遠(yuǎn)程計算機(jī),查看遠(yuǎn)程計算機(jī)有哪些文件,然后把文件從遠(yuǎn)程計算機(jī)上拷貝到本地計算機(jī),或者把本地計算機(jī)的文件送到遠(yuǎn)程計算機(jī)上。在Qt中,我們可以使用QNetworkAccessManager和QNetworkReply類來進(jìn)行FTP程序的編寫。但是,對于較復(fù)雜的FTP操作,Qt還提供了QFtp類。

在QFtp中,所有的操作都對應(yīng)一個特定的函數(shù),我們可以稱它們?yōu)槊睢H鏲onnectToHost()連接到效勞器命令,login()登錄命令,get()下載命令,mkdir()新建目錄命令等。?QFtp類以異步方式工作,所有的這些函數(shù)都不是阻塞函數(shù)。也就是說,如果一個操作不能立即執(zhí)行,那么這個函數(shù)就會直接返回,直到程序控制權(quán)返回Qt事件循環(huán)后才真正執(zhí)行,它們不會影響界面的顯示。3FTP編程所有的命令都返回一個int型的編號,使用這個編號讓我們可以跟蹤這個命令,查看其執(zhí)行狀態(tài)。每條命令開始執(zhí)行時,都會發(fā)出commandStarted()信號,該命令執(zhí)行結(jié)束時,會發(fā)出commandFinished()信號。可以利用這兩個信號和命令的編號來獲取命令的執(zhí)行狀態(tài)。可以使用currentCommand()獲取現(xiàn)在執(zhí)行的命令,其返回值與命令對應(yīng)關(guān)系如以下圖。3FTP編程-例子1?在這個例子中我們從FTP效勞器上下載一個文件并顯示出來。3FTP編程-例子1?Widget.h頭文件#include<QWidget>#include"QFtp"classWidget:publicQWidget{Q_OBJECTpublic:Widget(QWidget*parent=0);~Widget();protected:voidchangeEvent(QEvent*e);private:Ui::Widget*ui;QFtp*ftp;privateslots:voidftpCommandStarted(int);voidftpCommandFinished(int,bool);};

3FTP編程-例子1?Widget.cpp參考代碼Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);ftp=newQFtp(this);ftp->");//連接到效勞器ftp->login();//登錄ftp->cd("qt");//跳轉(zhuǎn)到“qt”目錄下ftp->get("INSTALL");//下載“INSTALL”文件ftp->close();//關(guān)閉連接connect(ftp,SIGNAL(commandStarted(int)),this,SLOT(ftpCommandStarted(int)));//當(dāng)每條命令開始執(zhí)行時發(fā)出相應(yīng)的信號connect(ftp,SIGNAL(commandFinished(int,bool)),this,SLOT(ftpCommandFinished(int,bool)));//當(dāng)每條命令執(zhí)行結(jié)束時發(fā)出相應(yīng)的信號}3FTP編程-例子1?Widget.cpp參考代碼voidWidget::ftpCommandStarted(int){if(ftp->currentCommand()==QFtp::ConnectToHost){ui->label->setText(tr("正在連接到效勞器…"));}if(ftp->currentCommand()==QFtp::Login){ui->label->setText(tr("正在登錄…"));}if(ftp->currentCommand()==QFtp::Get){ui->label->setText(tr("正在下載…"));}elseif(ftp->currentCommand()==QFtp::Close){ui->label->setText(tr("正在關(guān)閉連接…"));}}3FTP編程-例子1?Widget.cpp參考代碼voidWidget::ftpCommandFinished(int,boolerror){if(ftp->currentCommand()==QFtp::ConnectToHost){if(error)ui->label->setText(tr("連接效勞器出現(xiàn)錯誤:%1").arg(ftp->errorString()));elseui->label->setText(tr("連接到效勞器成功"));}if(ftp->currentCommand()==QFtp::Login){if(error)ui->label->setText(tr("登錄出現(xiàn)錯誤:%1").arg(ftp->errorString()));elseui->label->setText(tr("登錄成功"));}if(ftp->currentCommand()==QFtp::Get){if(error)ui->label->setText(tr("下載出現(xiàn)錯誤:%1").arg(ftp->errorString()));else{ui->label->setText(tr("已經(jīng)完成下載"));ui->textBrowser->setText(ftp->readAll());}}elseif(ftp->currentCommand()==QFtp::Close){ui->label->setText(tr("已經(jīng)關(guān)閉連接"));}}3FTP編程-例子2?該例子將例子1程序進(jìn)行擴(kuò)展,使其可以瀏覽并能下載效勞器上的所有文件。實現(xiàn)在用戶填寫完相關(guān)信息后,按下“連接”按鈕,就可以連接到FTP效勞器,并在TreeWidget中顯示效勞器上的所有文件,我們可以按下“下載”按鈕來下載選中的文件,并使用進(jìn)度條顯示下載進(jìn)度3FTP編程-例子2privateslots:voidon_downloadButton_clicked();voidon_cdToParentButton_clicked();voidon_connectButton_clicked();voidftpCommandFinished(int,bool);voidftpCommandStarted(int);voidupdateDataTransferProgress(qint64,qint64);//更新進(jìn)度條voidaddToList(constQUrlInfo&urlInfo);//將效勞器上的文件添加到TreeWidget中voidprocessItem(QTreeWidgetItem*,int);//雙擊一個目錄時顯示其內(nèi)容};Widget.h代碼如下:#include<QWidget>#include"QUrlInfo"#include"QTreeWidgetItem"#include"QFtp“#include”QFile”classWidget:publicQWidget{Q_OBJECTpublic:Widget(QWidget*parent=0);~Widget();protected:voidchangeEvent(QEvent*e);private:Ui::Widget*ui;QHash<QString,bool>isDirectory;QStringcurrentPath;QFtp*ftp;QFile*file;3FTP編程-例子2Widget.cpp代碼如下:#include"widget.h"#include"ui_widget.h"#include"QFtp"#include"QPixmap"#include"QFile"Widget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);ui->progressBar->setValue(0);connect(ui->fileList,SIGNAL(itemActivated(QTreeWidgetItem*,int)),this,SLOT(processItem(QTreeWidgetItem*,int)));//鼠標(biāo)雙擊列表中的目錄時,我們進(jìn)入該目錄}3FTP編程-例子2Widget.cpp代碼如下:voidWidget::on_connectButton_clicked(){ui->fileList->clear();currentPath.clear();isDirectory.clear();ftp=newQFtp(this);connect(ftp,SIGNAL(commandStarted(int)),this,SLOT(ftpCommandStarted(int)));connect(ftp,SIGNAL(commandFinished(int,bool)),this,SLOT(ftpCommandFinished(int,bool)));connect(ftp,SIGNAL(listInfo(QUrlInfo)),this,SLOT(addToList(QUrlInfo)));connect(ftp,SIGNAL(dataTransferProgress(qint64,qint64)),this,SLOT(updateDataTransferProgress(qint64,qint64)));QStringftpServer=this->ui->ftpServerlineEdit->text();QStringuserName=this->ui->userNamelineEdit->text();QStringpassWord=this->ui->passWordlineEdit->text();ftp->connectToHost(ftpServer,21);//連接到效勞器,默認(rèn)端口號是21ftp->login(userName,passWord);//登錄}3FTP編程-例子2Widget.cpp代碼如下:voidWidget::ftpCommandStarted(int){if(ftp->currentCommand()==QFtp::ConnectToHost){ui->label->setText(tr("正在連接到效勞器…"));}if(ftp->currentCommand()==QFtp::Login){ui->label->setText(tr("正在登錄…"));}if(ftp->currentCommand()==QFtp::Get){ui->label->setText(tr("正在下載…"));}elseif(ftp->currentCommand()==QFtp::Close){ui->label->setText(tr("正在關(guān)閉連接…"));}}3FTP編程-例子2Widget.cpp代碼如下:voidWidget::ftpCommandFinished(int,boolerror){if(ftp->currentCommand()==QFtp::Login){if(error)ui->label->setText(tr("登錄出現(xiàn)錯誤:%1").arg(ftp->errorString()));else{ui->label->setText(tr("登錄成功"));this->ftp->list();}}if(ftp->currentCommand()==QFtp::Get){if(error)ui->label->setText(tr("下載出現(xiàn)錯誤:%1").arg(ftp->errorString()));else{ui->label->setText(tr("已經(jīng)完成下載"));this->ui->downloadButton->setEnabled(true); this->file.close();}}if(ftp->currentCommand()==QFtp::List){if(isDirectory.isEmpty()){//如果目錄為空,顯示“empty”ui->fileList->addTopLevelItem(newQTreeWidgetItem(QStringList()<<tr("<empty>")));ui->fileList->setEnabled(false);ui->label->setText(tr("該目錄為空"));}}}3FTP編程-例子2Widget.cpp代碼如下:voidWidget::processItem(QTreeWidgetItem*item,int){QStringname=item->text(0);//返回第0列的文本值if(isDirectory.value(name)){//如果這個文件是個目錄,那么翻開ui->fileList->clear();isDirectory.clear();currentPath+='/';currentPath+=name;ftp->cd(name);ftp->list();ui->cdToParentButton->setEnabled(true);}}3FTP編程-例子2Widget.cpp代碼如下:voidWidget::on_cdToParentButton_clicked(){ui->fileList->clear();isDirectory.clear();currentPath=currentPath.left(currentPath.lastIndexOf('/'));if(currentPath.isEmpty()){ui->cdToParentButton->setEnabled(false);ftp->cd("/");}else{ftp->cd(currentPath);}ftp->list();}voidWidget::on_downloadButton_clicked(){QStringfileName=ui->fileList->currentItem()->text(0);this->file=newQFile(fileName);if(!file->open(QIODevice::WriteOnly)){deletefile;return;}ui->downloadButton->setEnabled(false);//下載按鈕不可用,等下載完成后才可用

ftp->get(ui->fileList->currentItem()->text(0),file);}3FTP編程-例子2Widget.cpp代碼如下:voidWidget::addToList(constQUrlInfo&urlInfo){ QTreeWidgetItem*item=newQTreeWidgetItem;item->setText(0,urlI());item->setText(1,QString::number(urlInfo.size()));item->setText(2,urlInfo.owner());item->setText(3,urlInfo.group());item->setText(4,urlInfo.lastModified().toString("MMMddyyyy"));QPixmappixmap(urlInfo.isDir()?"../dir.png":"../file.png");item->setIcon(0,pixmap);isDirectory[urlI()]=urlInfo.isDir();//存儲該路徑是否為目錄的信息

ui->fileList->addTopLevelItem(item);if(!ui->fileList->currentItem()){ui->fileList->setCurrentItem(ui->fileList->topLevelItem(0));ui->fileList->setEnabled(true);}}voidWidget::updateDataTransferProgress(qint64readBytes,qint64totalBytes){ui->progressBar->setMaximum(totalBytes);ui->progressBar->setValue(readBytes);}4獲取本機(jī)網(wǎng)絡(luò)信息?如果要獲取自己電腦的IP地址以及其他網(wǎng)絡(luò)信息。會涉及到網(wǎng)絡(luò)模塊〔QtNetworkModule〕中的QHostInfo,QHostAddress,QNetworkInterface和QNetworkAddressEntry等類?!?〕使用QHostInfo獲取主機(jī)名和IP地址獲取主機(jī)名字:QHostInfo::localHostName()獲取IP地址: QHostInfoinfo=QHostInfo::fromName(localHostName); qDebug()<<”IPAddress:“<<info.addresses();〔2〕通過QNetworkInterface類來獲取本機(jī)的IP地址和網(wǎng)絡(luò)接口信息QNetworkInterface類提供了程序所運(yùn)行時的主機(jī)的IP地址和網(wǎng)絡(luò)接口信息的列表。在每一個網(wǎng)絡(luò)接口信息中都包含了0個或多個IP地址,而每一個IP地址又包含了和它相關(guān)的子網(wǎng)掩碼和播送地址,它們?nèi)弑环庋b在一個QNetworkAddressEntry對象中。網(wǎng)絡(luò)接口信息中也提供了硬件地址信息。4獲取本機(jī)網(wǎng)絡(luò)信息?QList<QNetworkInterface>list=QNetworkInterface::allInterfaces();//獲取所有網(wǎng)絡(luò)接口的列表foreach(QNetworkInterfaceinterface,list)//遍歷每一個網(wǎng)絡(luò)接口{qDebug()<<"Device:"<<();//設(shè)備名qDebug()<<"HardwareAddress:"<<interface.hardwareAddress();//硬件地址QList<QNetworkAddressEntry>entryList=interface.addressEntries();//獲取IP地址條目列表,每個條目中包含一個IP地址,一個子網(wǎng)掩碼和一個播送地址foreach(QNetworkAddressEntryentry,entryList)//遍歷每一個IP地址條目{qDebug()<<"IPAddress:"<<entry.ip().toString();//IP地址qDebug()<<"Netmask:"<<mask().toString();//子網(wǎng)掩碼qDebug()<<"Broadcast:"<<entry.broadcast().toString();//播送地址}}4獲取本機(jī)網(wǎng)絡(luò)信息?常用的獲取IP地址的方法:QStringWidget::getIP()

//獲取ip地址

{

QList<QHostAddress>list=QNetworkInterface::allAddresses();

foreach(QHostAddressaddress,list)

{

if(tocol()==QAbstractSocket::IPv4Protocol)

returnaddress.toString();

}

return0;

}5UDP編程?UDP〔UserDatagramProtocol即用戶數(shù)據(jù)報協(xié)議〕是一個輕量級的,不可靠的,面向數(shù)據(jù)報的無連接協(xié)議。騰訊QQ,其聊天時就是使用UDP協(xié)議進(jìn)行消息發(fā)送的。就像QQ那樣,當(dāng)有很多用戶,發(fā)送的大局部都是短消息,要求能及時響應(yīng),并且對平安性要求不是很高的情況下使用UDP協(xié)議。在Qt中提供了QUdpSocket類來進(jìn)行UDP數(shù)據(jù)報〔datagrams〕的發(fā)送和接收。這里我們還要了解一個名詞Socket,也就是常說的“套接字”。Socket簡單地說,就是一個IP地址加一個port端口。因為我們要傳輸數(shù)據(jù),就要知道往哪個機(jī)子上傳送,而IP地址確定了一臺主機(jī),但是這臺機(jī)子上可能運(yùn)行著各種各樣的網(wǎng)絡(luò)程序,我們要往哪個程序中發(fā)送呢?這時就要使用一個端口來指定UDP程序。所以說,Socket指明了數(shù)據(jù)報傳輸?shù)穆窂健?UDP編程?例子:編寫兩個程序,一個用來發(fā)送數(shù)據(jù)報,可以叫做客戶端;另一個用來接收數(shù)據(jù)報,可以叫做效勞器端,它們均應(yīng)用UDP協(xié)議。這樣也就構(gòu)成了所謂的C/S〔客戶端/效勞器〕編程模型??蛻舳说慕缑嫒缫韵聢D:5UDP編程?“開始播送”按鈕的單擊事件槽函數(shù):voidWidget::on_pushButton_clicked()

//發(fā)送播送{

QByteArraydatagram=“helloworld!”;

sender->writeDatagram(datagram.data(),datagram.size(),

QHostAddress::Broadcast,45454);}這里我們定義了一個QByteArray類型的數(shù)據(jù)報datagram,其內(nèi)容為“helloworld!”。然后使用QUdpSocket類的writeDatagram()函數(shù)來發(fā)送數(shù)據(jù)報,這個函數(shù)有四個參數(shù),分別是數(shù)據(jù)報的內(nèi)容,數(shù)據(jù)報的大小,主機(jī)地址和端口號。對于數(shù)據(jù)報的大小,它根據(jù)平臺的不同而不同,但是這里建議不要超過512字節(jié)。這里我們使用了播送地址QHostAddress::Broadcast,這樣就可以同時給網(wǎng)絡(luò)中所有的主機(jī)發(fā)送數(shù)據(jù)報了。對于端口號,它是可以隨意指定的,但是一般1024以下的端口號通常屬于保存端口號,所以我們最好使用大于1024的端口,最大為65535。我們這里使用了45454這個端口號,一定要注意,在下面要講的效勞器程序中,也要使用相同的端口號。5UDP編程?效勞器端的界面如以下圖:receiver=newQUdpSocket(this);receiver->bind(45454,QUdpSocket::ShareAddress);connect(receiver,SIGNAL(readyRead()),this,SLOT(processPendingDatagram()));構(gòu)造函數(shù)中將receiver綁定到45454端口,這個端口就是上面發(fā)送端設(shè)置的端口,二者必須一樣才能保證接收到數(shù)據(jù)報。我們這里使用了綁定模式QUdpSocket::ShareAddress,它說明其他效勞也可以綁定到這個端口上。當(dāng)receiver發(fā)現(xiàn)有數(shù)據(jù)報到達(dá)時就會發(fā)出readyRead()信號,將其和數(shù)據(jù)報處理函數(shù)相關(guān)聯(lián)。5UDP編程?voidWidget::processPendingDatagram()//處理等待的數(shù)據(jù)報{while(receiver->hasPendingDatagrams())//擁有等待的數(shù)據(jù)報

{QByteArraydatagram;//擁于存放接收的數(shù)據(jù)報

datagram.resize(receiver->pendingDatagramSize());//讓datagram的大小為等待處理的數(shù)據(jù)報的大小,這樣才能接收到完整的數(shù)據(jù)

receiver->readDatagram(datagram.data(),datagram.size());//接收數(shù)據(jù)報,將其存放到datagram中

ui->label->setText(datagram);//將數(shù)據(jù)報內(nèi)容顯示出來

}}5UDP編程?先運(yùn)行效勞器端程序,再運(yùn)行客戶端程序。然后點擊其上的“發(fā)送播送”按鈕,這時會顯示數(shù)據(jù)報的內(nèi)容。可以看到,UDP的應(yīng)用是很簡單的。我們只需要在發(fā)送端執(zhí)行writeDatagram()函數(shù)進(jìn)行數(shù)據(jù)報的發(fā)送,然后在接收端綁定端口,并關(guān)聯(lián)readyRead()信號和數(shù)據(jù)報處理函數(shù)即可。改程序運(yùn)行效果如以下圖:5UDP編程?例子:聊天程序:5UDP編程?參考代碼如下:Widget.hclassWidget:publicQWidget{Q_OBJECTpublic:Widget(QWidget*parent=0);~Widget();voidsendmessage();QStringgetIP();QStringgetmessage();protected:voidchangeEvent(QEvent*e);private:Ui::Widget*ui;QUdpSocket*udpsocket;privateslots:voidon_SendpushButton_clicked();voidprocesspendingdatagram();};5UDP編程?參考代碼如下:Widget.cppWidget::Widget(QWidget*parent):QWidget(parent),ui(newUi::Widget){ui->setupUi(this);this->ui->lineEdit->setFocus();this->udpsocket=newQUdpSocket(this);this->udpsocket->bind(45454,QUdpSocket::ShareAddress|QUdpSocket::ReuseAddressHint);connect(this->udpsocket,SIGNAL(readyRead()),this,SLOT(processpendingdatagram()));}5UDP編程?參考代碼如下:Widget.cppvoidWidget::on_SendpushButton_clicked(){sendmessage();}voidWidget::sendmessage(){QByteArraydata;QDataStreamout(&data,QIODevice::WriteOnly);QStringlocalhostname=QHostInfo::localHostName();QStringaddress=this->getIP();out<<localhostname<<address<<getmessage();this->udpsocket->writeDatagram(data,data.length(),QHostAddress::Broadcast,45454);}5UDP編程?參考代碼如下:Widget.cppQStringWidget::getIP(){QList<QHostAddress>list=QNetworkInterface::allAddresses();foreach(QHostAddressaddress,list){if(tocol()==QAbstractSocket::IPv4Protocol)

returnaddress.toString();}return0;}QStringWidget::getmessage()//獲得要發(fā)送的信息{QStringmsg=this->ui->lineEdit->text();ui->lineEdit->clear();ui->lineEdit->setFocus();returnmsg;}5UDP編程?參考代碼如下:Widget.cppvoidWidget::processpendingdatagram(){while(this->udpsocket->hasPendingDatagrams()){QByt

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論