效果圖:
QT編寫TCP/UDP調試助手之UDP通信,支持單播、組播和廣播三種通信模式。
一、前言
UDP(用戶數據報協議)是一種簡單輕量級、不可靠、面向數據報,無連接的傳輸層協議,也就是發送數據前不需要握手連接,只要知道IP和端口號就能發送數據,但是對方能不能收到,收到的對不對就不得而知了。
UDP通信中分爲三種通信方式,分別爲單播、組播和廣播,主要就是IP的區別。
二、關鍵代碼
1.在.pro文件中添加QT += network,包含頭文件#include <QUdpSocket>
在類裏定義一個QTcpSocket*成員m_udpSocket
2.界面校驗設置。界面上有四個lineEdit用來填寫IP和端口,通過setValidator可以限制lineEdit輸入的範圍,端口號範圍0-65535,IP地址用正則表達式校驗,防止輸入錯誤。
//設置端口輸入校驗
ui->lineEdit_udpLocalPort->setValidator(new QIntValidator(0,65535));
ui->lineEdit_udpRemotePort->setValidator(new QIntValidator(0,65535));
//ip校驗正則
QRegExp regExpIP("((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[\\.]){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])");
//設置IP輸入校驗
ui->lineEdit_udpLocalIP->setValidator(new QRegExpValidator(regExpIP ,ui->lineEdit_udpLocalIP));
ui->lineEdit_udpRemoteIP->setValidator(new QRegExpValidator(regExpIP ,ui->lineEdit_udpRemoteIP));
3.綁定端口,綁定端口後收到數據時會發射readyRead()信號
//綁定端口
this->m_udpSocket->bind(localip,port,QAbstractSocket::ShareAddress);
//連接接收信號槽
connect(m_udpSocket,SIGNAL(readyRead()),this,SLOT(UdpReadData()));
4.接收數據槽函數,注意和TcpSocket不同,不是直接調用readAll()
//udp接收消息
void MainWindow::UdpReadData()
{
//獲取發來的數據
QByteArray datagram;
while (m_udpSocket->hasPendingDatagrams())
{
//等待接收的字節數
int sizeLen=static_cast<int>(m_udpSocket->pendingDatagramSize());
datagram.resize(sizeLen);
//讀取
m_udpSocket->readDatagram(datagram.data(),datagram.size());
}
QString data;
//hex
if(ui->chk_udpRecHex->isChecked())
{
this->ByteToHexString(data,datagram);
}
else//普通字符串
{
data=QString::fromLocal8Bit(datagram);
}
//顯示
ui->text_udpRec->insertPlainText(data);
ui->text_udpRec->moveCursor(QTextCursor::End);
}
5.選擇組播通信模式時,可以勾選加入組播,接收組播數據。
組播是udp實現一對多通信的一種方式,一個udp客戶端往該IP發消息,加入該組的客戶端都會收到消息。組播IP地址爲D類地址,範圍224.0.0.0~239.255.255.255。
5.1判斷IP地地址在224.0.0.0~239.255.255.255範圍內
//獲取組播Ip
bool ok;
QHostAddress groupip(ui->lineEdit_GroupIp->text());
groupip.toIPv4Address(&ok);
if(!ok)
{
QMessageBox::warning(this,"錯誤","組播IP輸入有誤,請重新輸入");
ui->chk_udpGroup->setChecked(false);
return;
}
//D類IP地址的範圍爲224.0.0.0~239.255.255.255。前4比特固定爲1110,後28比特是組播組地址標識(ID)
QPair<QHostAddress, int> subnet = QHostAddress::parseSubnet("224.0.0.0/4");
bool is_DClass = groupip.isInSubnet(subnet);
if(!is_DClass)
{
QMessageBox::warning(this,"錯誤","組播IP應在D類IP地址範圍224.0.0.0~239.255.255.255內,請重新輸入");
ui->chk_udpGroup->setChecked(false);
return;
}
5.2加入\退出組播IP組,加入後有數據會發射readyRead()信號,就能接收數據了
//加入組
m_udpSocket->joinMulticastGroup(groupip);
//退出組
m_udpSocket->leaveMulticastGroup(currentIP);
6.發送數據,調用m_udpSocket->writeDatagram(byteArray,ip,port)發送,單播、組播和廣播就是IP不同,這裏就體現出來了。
6.1單播:IP地址任意,例如:
m_udpSocket->writeDatagram(byteArray,QHostAddress("192.168.206.100"),port);
6.2組播:IP是D類地址,範圍224.0.0.0~239.255.255.255,有加入組的客戶端纔會收到數據,例如:
m_udpSocket->writeDatagram(byteArray,QHostAddress("224.0.0.2"),port);
6.3廣播:IP設置爲QHostAddress::Broadcast,相當於QHostAddress("255.255.255.255").,廣播數據會發送給局域網內的每個客戶端,例如:
m_udpSocket->writeDatagram(byteArray,QHostAddress::Broadcast,port);
7.注意事項
前面都在說IP,其實端口也很重要,端口一定要對應,不然會收不到數據,例如:
7.1組播通信,本地綁定的是192.168.206.1:6666,並加入組播IP 224.0.0.2。對方往224.0.0.2:1234發數據本地是收不到的,因爲端口不對,要往224.0.0.2:6666發才收得到。
7.1廣播也是如此,writeDatagram(byteArray,QHostAddress::Broadcast,1234);廣播發的是1234端口,那局域網內的客戶端也必須綁定的是1234端口,纔會收到數據。