目標:實現一個界面發送和接收
注意:要在工程名的右鍵菜單中勾選NetWork library,並且在頭文件中加上#include <QtNetwork>
1. UDP套接字
UDP套接字就是一個IP地址加一個port端口,因爲我們要傳輸數據,就要知道往哪個機子上傳送,而IP地址確定了一臺主機,但是這臺機子上可能運行着各種各樣的網絡程序,我們要往哪個程序中發送呢?這時就要使用一個端口來指定UDP程序。在使用前不需要進行連接。TCP協議與電話通信相似,而UDP協議則與郵件通信相似:你寄包裹或信件時不需要進行”連接”,但是你得爲每個包裹和信件指定目的地址。類似的,每條信息(即數據報文,datagram)負載了自己的地址信息,並與其他信息相互獨立。在接收信息時,UDP套接字扮演的角色就像是一個信箱,從不同地址發送來的信件和包裹都可以放到裏面。一旦被創建,UDP套接字就可以用來連續地向不同的地址發送信息,或從任何地址接收信息。
UDP套接字與TCP套接字的另一個不同點在於他們對信息邊界的處理方式不同:UDP套接字將保留邊界信息。這個特性使應用程序在接受信息時,從某些方面來說比使用TCP套接字更簡單。
最後一個不同點是,UDP協議所提供的端到端傳輸服務是盡力而爲(best-effort)的,即UDP套接字將儘可能地傳送信息,但並不保證信息一定能成功到達目的地址,而且信息到達的順序與其發送順序不一定一致(就像通過郵政部門寄信一樣)。因此,使用了UDP套接字的程序必須準備好處理信息的丟失和重排。
2. 目標界面
- 頭文件裏面的聲明
private:
Ui::UDPMsgClass ui;
QUdpSocket *udp_socket_rx;//接收端套接字
QUdpSocket *udp_socket_tx;//發送端套接字
QHostAddress Ip_tx;//發送端IP
int Port_tx;//發送端Port
private slots:
void on_btn_cfg_clicked();//配置按鈕函數
void on_btn_tx_clicked();//發送按鈕函數
void on_btn_clear_clicked();//清除按鈕函數
void rx_udp();//接收處理函數
- c文件的編寫
首先,在構造函數裏面進行信號與槽函數的綁定。
udp_socket_rx = new QUdpSocket(this);
udp_socket_tx = new QUdpSocket(this);
connect(ui.Btn_tx, SIGNAL(clicked()), this, SLOT(on_btn_tx_clicked()) );
connect(ui.Btn_cfg, SIGNAL(clicked()), this, SLOT(on_btn_cfg_clicked()) );
connect(ui.Btn_clear, SIGNAL(clicked()), this, SLOT(on_btn_clear_clicked()) );
connect(udp_socket_rx, SIGNAL(readyRead()), this, SLOT(rx_udp()));//當接收套接字接收到數據時,轉到rx_udp()函數進行處理
ui.Btn_tx->setEnabled(false);//設置爲不可按下
然後,再實現各個槽函數。
void UDPMsg::on_btn_clear_clicked(){//清屏函數
ui.Bro_rx->clear();
ui.Bro_tx->clear();
}
void UDPMsg::on_btn_cfg_clicked(){//配置函數
bool ok;
int Port_rx = 0;
Ip_tx = QHostAddress(ui.Line_TxIP->text());
Port_tx = ui.Line_TxPort->text().toInt(&ok);
Port_rx = ui.Line_RxPort->text().toInt(&ok);
udp_socket_rx->bind(Port_rx,QHostAddress::ShareAddress);//接收的套接字綁定相應的Port和IP
ui.Btn_tx->setEnabled(true);//激活發送按鈕
}
void UDPMsg::rx_udp(){//接收處理函數
while (udp_socket_rx->hasPendingDatagrams())//當接收到報文數據時
{
QByteArray datagram;//因爲傳送來的數據類型是未知,所以用Bytearray
datagram.resize(udp_socket_rx->pendingDatagramSize());//datagram的數據大小取決於接收到的數據
udp_socket_rx->readDatagram(datagram.data(), datagram.size());//讀取數據
ui.Bro_rx->append(datagram);//將報文顯示到接收框
}
}
void UDPMsg::on_btn_tx_clicked(){//發送按鈕處理函數
QByteArray datagram = ui.Bro_tx->toPlainText().toAscii();
udp_socket_tx->writeDatagram(datagram, datagram.size(), Ip_tx, Port_tx);
}
注:因爲是實現的同一個界面既發送又接收數據,所以其UDP端口號也要一樣的,這樣才能夠正常的接收到發送的數據