閱讀852 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[Qt教程] 第36篇 網絡(六)UDP

[Qt教程] 第36篇 網絡(六)UDP

樓主
 發表於 2013-9-5 11:38:50 | 查看: 241| 回複: 0
UDP

版權聲明

該文章原創作者yafeilinux,轉載請注明出處!



導語

這一節講述UDP編程的知識。UDP(UserDatagram Protocol即用戶數據報協議)是一個輕量級的,不可靠的,麵向數據報的無連接協議。對於UDP我們不再進行過多介紹,如果你對UDP不是很了解,而且不知道它有什麼用,那麼這裏就舉個簡單的例子:我們現在幾乎每個人都使用的騰訊QQ,其聊天時就是使用UDP協議進行消息發送的。就像QQ那樣,當有很多用戶,發送的大部分都是短消息,要求能及時響應,並且對安全性要求不是很高的情況下使用UDP協議。
    在Qt中提供了QUdpSocket 類來進行UDP數據報(datagrams)的發送和接收。這裏我們還要了解一個名詞Socket,也就是常說的“套接字”。 Socket簡單地說,就是一個IP地址加一個port端口。因為我們要傳輸數據,就要知道往哪個機子上傳送,而IP地址確定了一台主機,但是這台機子上可能運行著各種各樣的網絡程序,我們要往哪個程序中發送呢?這時就要使用一個端口來指定UDP程序。所以說,Socket指明了數據報傳輸的路徑。
下麵我們將編寫兩個程序,一個用來發送數據報,可以叫做客戶端;另一個用來接收數據報,可以叫做服務器端,它們均應用UDP協議。這樣也就構成了所謂的C/S(客戶端/服務器)編程模型。我們會在編寫程序的過程中講解一些相關的網絡知識。




環境:Windows Xp + Qt 4.8.5+QtCreator 2.8.0




目錄


一、發送端(客戶端)
二、接收端(服務器端)





正文



一、發送端(客戶端)


1.新建Qt Gui應用。
項目名為udpSender,基類選擇QWidget,類名為Widget。完成後在udpSender.pro文件中添加一行代碼:QT += network,並保存該文件。


2.widget.ui文件中,往界麵上添加一個Push Button,更改其顯示文本為“開始廣播”,然後進入其單擊事件槽函數。


3.我們在widget.h文件中更改。
添加頭文件:#include <QtNetwork>
添加private私有對象:QUdpSocket *sender;


4.我們在widget.cpp中進行更改。
在構造函數中添加:sender = new QUdpSocket(this);
更改“開始廣播”按鈕的單擊事件槽函數:
void Widget::on_pushButton_clicked() // 開始廣播
{
    QByteArray datagram = "hello world!";
    sender->writeDatagram(datagram.data(),datagram.size(),
                          QHostAddress::Broadcast,45454);
}


這裏定義了一個QByteArray類型的數據報datagram,其內容為“hello world!”。然後我們使用QUdpSocket類的writeDatagram()函數來發送數據報,這個函數有四個參數,分別是數據報的內容,數據報的大小,主機地址和端口號。對於數據報的大小,它根據平台的不同而不同,但是這裏建議不要超過512字節。這裏使用了廣播地址QHostAddress::Broadcast,這樣就可以同時給網絡中所有的主機發送數據報了。對於端口號,它是可以隨意指定的,但是一般1024以下的端口號通常屬於保留端口號,所以我們最好使用大於1024的端口,最大為65535。我們這裏使用了45454這個端口號,一定要注意,在下麵要講的服務器程序中,也要使用相同的端口號。

5.發送端就這麼簡單,下麵可以先運行程序。




二、接收端(服務器端)


1.新建Qt Gui 應用
工程名為udpReceiver,基類選擇QWidget,類名為Widget。完成後在udpSender.pro文件中添加一行代碼:QT += network,並保存該文件。
此時工程文件列表中應包含兩個項目,如下圖。


01.jpg



2.我們在udpReceiver項目中的widget.ui文件中,向界麵上添加一個Label部件,更改其顯示文本為“等待接收數據!”,效果如下。



3.我們在udpReceiver工程中的widget.h文件中更改。
添加頭文件:#include <QtNetwork>
添加private私有對象:QUdpSocket *receiver;
添加私有槽函數:
private slots:
void processPendingDatagram();


4.我們在udpReceiver工程中的widget.cpp文件中更改。
在構造函數中:
receiver = new QUdpSocket(this);
receiver->bind(45454,QUdpSocket::ShareAddress);
connect(receiver,SIGNAL(readyRead()),
this,SLOT(processPendingDatagram()));

我們在構造函數中將receiver綁定到45454端口,這個端口就是上麵發送端設置的端口,二者必須一樣才能保證接收到數據報。這裏使用了綁定模式QUdpSocket::ShareAddress,它表明其他服務也可以綁定到這個端口上。因為當receiver發現有數據報到達時就會發出readyRead()信號,所以將其和數據報處理函數相關聯。

數據報處理槽函數實現如下:


void Widget::processPendingDatagram() //處理等待的數據報
{
    while(receiver->hasPendingDatagrams())  //擁有等待的數據報
    {
       QByteArray datagram; //擁於存放接收的數據報
//讓datagram的大小為等待處理的數據報的大小,這樣才能接收到完整的數據
       datagram.resize(receiver->pendingDatagramSize());
       //接收數據報,將其存放到datagram中
       receiver->readDatagram(datagram.data(),datagram.size());
       //將數據報內容顯示出來
       ui->label->setText(datagram);
    }
}



5.我們在項目列表中udpReceiver項目上點擊鼠標右鍵,在彈出的菜單上選擇run菜單來運行該工程。如下圖所示。


02.jpg



6.第一次運行該程序時,係統可能會提示警告,我們選擇“解除阻止”。
注意,如果是在linux下,你可能還需要關閉防火牆。


7.我們同時再運行udpSender程序。然後點擊其上的“發送廣播”按鈕,這時會在udpReceiver上顯示數據報的內容。效果如下。



03.jpg



結語


可以看到,UDP的應用是很簡單的。我們隻需要在發送端執行writeDatagram()函數進行數據報的發送,然後在接收端綁定端口,並關聯readyRead()信號和數據報處理函數即可。
    下一節我們講述TCP的應用。





涉及到的源碼:  udpSender.rar (1.6 KB, 下載次數: 4)  udpReceiver.rar (1.86 KB, 下載次數: 4) 



最後更新:2017-04-03 14:54:15

  上一篇:go [Qt教程] 第20篇 2D繪圖(十)圖形視圖框架(下)
  下一篇:go [Qt教程] 第45篇 進階(五)Qt樣式表