Qt 实例18 UDP单播/广播

f9bee3a3fcabad183fa680229c5d6911.png

本机运行两个实例需要绑定不同的端口,例如实例A绑定端口2000,实例B绑定端口3000,实例A向实例B发送数据时,需要指定实例B所在主机的IP地址、绑定端口作为目标地址和目标端口,这样实例B才能接收到数据报。如果在不同的计算机运行,则可以使用相同的端口。

  • 要实现数据接收,必须先使用QUdpSocket::bind()绑定一个端口,用于监听传入的数据报。解除绑定则使用abort()函数。

  • writeDatagram()函数向一个目标用户发送消息时,需要指定目标地址和端口。

  • 在广播消息时,只需要将目标地址更换为一个特殊地址,即广播地址QHostAddress::Broadcast,一般为255.255.255.255

  • 发送的数据报是QByteArray类型的字节数组,数据报的长度一般不超过512字节,可以是文本,也可以是二进制数据。

  • 接收到数据报后会发射readyRead()信号。

#ifndef WIDGET_H
#define WIDGET_H
 
#include <QWidget>
#include <QUdpSocket>
 
namespace Ui {
class Widget;
}
 
class Widget : public QWidget
{
    Q_OBJECT
 
public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();
 
private slots:
    void on_btnBind_clicked();
 
    void on_btnUnBind_clicked();
 
    void on_btnClear_clicked();
 
    void on_btnQuit_clicked();
 
    void on_btnSend_clicked();
 
    void on_btnBroadcast_clicked();
 
    void on_readyRead();
private:
    Ui::Widget *ui;
 
private:
    QUdpSocket *m_udpSocket = nullptr;
};
 
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include <QHostInfo>
 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
 
 
    //本地主机名
    QString hostName = QHostInfo::localHostName();
 
    //本机IP地址
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
 
    //IP地址列表
    QList<QHostAddress> addrList = hostInfo.addresses();
    for(int i=0;i<addrList.count();i++)
    {
        QHostAddress host = addrList.at(i);
 
        if(QAbstractSocket::IPv4Protocol == host.protocol())
        {
            QString ip = host.toString();
            ui->comboBox->addItem(ip);
        }
    }
 
    m_udpSocket = new QUdpSocket(this);
    connect(m_udpSocket,&QUdpSocket::readyRead,this,&Widget::on_readyRead);
 
}
 
Widget::~Widget()
{
    delete ui;
}
 
void Widget::on_btnBind_clicked()
{
    //本机UDP端口
    qint16 port = ui->spinBindPort->value();
 
    if(m_udpSocket->bind(port))
    {
        ui->plainTextEdit->appendPlainText("**已成功绑定");
        ui->plainTextEdit->appendPlainText("**绑定端口: "+QString::number(m_udpSocket->localPort()));
        ui->btnBind->setEnabled(false);
        ui->btnUnBind->setEnabled(true);
    }
    else
    {
         ui->plainTextEdit->appendPlainText("**绑定失败");
    }
}
 
void Widget::on_btnUnBind_clicked()
{
    //解除绑定
    m_udpSocket->abort();
    ui->btnBind->setEnabled(true);
    ui->btnUnBind->setEnabled(false);
    ui->plainTextEdit->appendPlainText("**已解除绑定");
}
 
void Widget::on_btnClear_clicked()
{
    ui->plainTextEdit->clear();
}
 
void Widget::on_btnQuit_clicked()
{
 
}
 
void Widget::on_btnSend_clicked()//单播
{
    //目标IP
    QString dstIp = ui->comboBox->currentText();
 
    QHostAddress dstAddr(dstIp);
 
    //目标端口
    quint16 dstPort = ui->spinDstPort->value();
 
    QString msg = ui->lineEdit->text();
    QByteArray str = msg.toUtf8();
 
    //发出数据报
    m_udpSocket->writeDatagram(str,dstAddr,dstPort);
 
    ui->plainTextEdit->appendPlainText("[out] "+msg);
}
 
void Widget::on_btnBroadcast_clicked()//广播
{
    quint16 dstPort = ui->spinDstPort->value();
 
    QString msg = ui->lineEdit->text();
    QByteArray str = msg.toUtf8();
 
    //发出数据报
    m_udpSocket->writeDatagram(str,QHostAddress::Broadcast,dstPort);
 
    ui->plainTextEdit->appendPlainText("[Broadcast] "+msg);
}
 
void Widget::on_readyRead()
{
    //是否还有待读取的传入数据报
    while(m_udpSocket->hasPendingDatagrams())
    {
        QByteArray data;
 
        //返回待读取的数据报的字节数
        data.resize(m_udpSocket->pendingDatagramSize());
 
        QHostAddress peerAddr;
 
        quint16 peerPort;
 
        //读取数据报的内容
        m_udpSocket->readDatagram(data.data(),data.size(),&peerAddr,&peerPort);
 
        QString str = data.data();
 
        QString peer = "[From ] +"+peerAddr.toString()+":"+QString::number(peerPort)+"] ";
 
        ui->plainTextEdit->appendPlainText(peer+str);
    }
}

原文链接:https://blog.csdn.net/wzz953200463/article/details/115101133

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值