一、單播
1、聲明udp對象
QUdpSocket* udpClient;
2、new出對象
udpClient = new QUdpSocket(this);
3、分配本地地址(如果不分配,使用系統自動分配的),設置接收槽函數
udpClient.bind("192.168.1.1”,8080);
QObject::connect(this->udpClient,SIGNAL(readyRead()),this,SLOT(rcvData()));
4、接收函數
void Udp::rcvData()
{
if(this->udpClient->pendingDatagramSize() == 0)
return;
QByteArray ba;
ba.resize(udpClient->pendingDatagramSize());
QHostAddress tempHost("");
quint16 port = 0;
this->udpClient->readDatagram(ba.data(),udpClient->pendingDatagramSize(),&tempHost,&port);
}
5、發送
void Udp::on_pushButton_3_clicked()
{
if(j == this->udpClient->writeDatagram(tempChar,j,ipAddress,port))
{
qDebuf()<<"發送成功"
}
}
6、關閉
udpClient.close();
ps:1、udp套接字bind成功之后,狀態是BoundState,close之后是UnconnectedState;
2、bind是將一個ip和地址綁定,並使socket與這兩個綁定在一起,通常是udp使用此函數;connectToHost是套接字連接至主機ip和端口,通常是tcp客戶端連接至服務器使用此函數;
3、每當udp的readyRead信號發出來后,一定要使用接收函數把數據接收了,否則下次來數據的時候不會發出此信號。
二、組播
組播:假設一個局域網內有多個計算機,每個計算機有一個IP,定義一個組播IP,把局域網中的某些計算機加入此組播IP,然后發送端向這個組播IP發送數據就完成了組播過程。
三、廣播
向255:255:255:255發送
ps:路由器會過濾多播(組播和廣播)
PS:開發流程

四、封裝
頭文件
#ifndef MYUDP_H #define MYUDP_H #include <QObject> #include <QUdpSocket> class Myudp : public QObject { Q_OBJECT public: explicit Myudp(QObject *parent = nullptr); ~Myudp(); void init(QString ip,uint port); private: QUdpSocket* udp; signals: void initSignal(QString ip,uint port); void quitSignal(); void sendDataSignal(const QByteArray&); public slots: void initSlot(QString ip,uint port); void quitSlot(); void rcvDataSlot(); void sendUdpSlot(QString ip,uint port,QString info); }; #endif // MYUDP_H
源文件
#include "myudp.h" #include "includes.h" #include "mymethod.h" /*****************************************************************/ //作者:朱小勇 //函數名稱:構造函數 //函數參數:NULL //函數返回值:NULL //函數作用:NULL //備注:NULL /*****************************************************************/ Myudp::Myudp(QObject *parent) : QObject(parent) { emit quitSignal(); } /*****************************************************************/ //作者:朱小勇 //函數名稱:初始化 //函數參數:NULL //函數返回值:NULL //函數作用:綁定udp端口 //備注:NULL /*****************************************************************/ void Myudp::init(QString ip,uint port) { QObject::connect(this,SIGNAL(initSignal(QString,uint)),this,SLOT(initSlot(QString,uint))); QObject::connect(this,SIGNAL(quitSignal()),this,SLOT(quitSlot())); emit initSignal(ip,port); } /*****************************************************************/ //作者:朱小勇 //函數名稱:析構函數 //函數參數:NULL //函數返回值:NULL //函數作用:NULL //備注:NULL /*****************************************************************/ Myudp::~Myudp() { } /*****************************************************************/ //作者:朱小勇 //函數名稱:初始化 //函數參數:NULL //函數返回值:NULL //函數作用:NULL //備注:NULL /*****************************************************************/ void Myudp::initSlot(QString ip,uint port) { if(nullptr!=udp) { udp->close(); delete udp; udp = NULL; } Mymethod::record(QString("ready to bind udp port,%1:%2.").arg(ip).arg(port),PRINT_NORMAL); udp = new QUdpSocket(); if(udp->bind(QHostAddress(ip),port)) { Mymethod::record("bind success.",PRINT_NORMAL); QObject::connect(udp,SIGNAL(readyRead()),this,SLOT(rcvDataSlot())); } else { Mymethod::record("bind failed.",PRINT_ERR); } } /***********************************************/ // 作者:朱小勇 // 函數名稱:回收內存槽函數,不能在析構函數里回收,因為析構函數也屬於主線程 // 函數作用:NULL // 函數參數:NULL // 函數返回值:NULL // 備注:NULL /***********************************************/ void Myudp::quitSlot() { if(nullptr!=udp) { udp->close(); delete udp; udp = NULL; } Mymethod::record("recycle udp resource",PRINT_INFO); } /*****************************************************************/ //作者:朱小勇 //函數名稱:數據接收 //函數參數:NULL //函數返回值:NULL //函數作用:NULL //備注:目前只接收SQL_CODE_開頭的字符串,其他過濾 /*****************************************************************/ void Myudp::rcvDataSlot() { QByteArray ba; if(udp->hasPendingDatagrams()) { ba.resize(udp->pendingDatagramSize()); QHostAddress sender; quint16 senderPort; udp->readDatagram(ba.data(), ba.size(),&sender, &senderPort); } if(ba.size()!=VALUE_0) { emit sendDataSignal(ba); } } /*****************************************************************/ //作者:朱小勇 //函數名稱:發送槽函數 //函數參數:NULL //函數返回值:NULL //函數作用:NULL //備注:使用local8bit傳輸格式 /*****************************************************************/ void Myudp::sendUdpSlot(QString ip, uint port, QString info) { RET_IF_EAQU(nullptr,udp); if(VALUE__1 == udp->writeDatagram(info.toUtf8(),QHostAddress(ip),port)) { Mymethod::record(getCodeLocate()+"udp send failed.",PRINT_ERR); } }
PS:
1、使用Qt的UDP綁定端口8000,往一個端口8001發送數據,如果這個8001端口沒有被其他UDP建立,則本端口8000會收到一個“0.0.0.0”:55560的空字符串!!!!!我這里是55560,不知道都是這個端口還是隨機的。
這個問題讓我查找了很久,一直不知道為啥8000接收打印,一直打印空字符串,后來關閉它的發送就沒收到了,說明它發送一個非UDP端口則有這樣一個反饋。
不知道這個設計是UDP協議本身的,還是QT自作聰明設計的,感覺非常雞肋,UDP本來就是不可靠傳輸,沒必要告訴我發送成功與否,害我找了半天答案,真tm無語。
