Qt+UDP及封裝


一、單播

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無語。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM