QUdpSocket实现UDP通信

转自:https://blog.csdn.net/m0_37357063/article/details/80744011
UDP(User Datagram Protocol, 用户数据报协议) 是轻量的、不可靠的、面向数据报、无连接的协议,它可以用于对可靠性要求不高的场所。UDP发送和接收数据都不需要建立连接,只需要绑定IP地址和端口号就可以了。发送数据直接发送,接收数据需要循环判断数据是否接受完毕。Qt的信号槽机制很好的实现了收到数据发送信号触发处理函数。

QUdpSocket类用于UDP通信,它是从QAbstractSocket继承而来的,所以与QTcpSocket共享大部分的接口函数。主要区别是QUdpSocket以数据报传输数据,而不是连续的数据流。发送数据报使用函数QUdpSocket::writeDatagram(),数据报的长度一般少于512字节,每个数据报包含发送者和接受者的IP地址和端口信息。

要进行UDP数据接收,要用QUdpSocket::bind()函数先绑定一个端口,用于接收传入的数据报。当有数据报传入时会发射readRead()信号,使用readDatagram()函数来读取接收到的数据报。

UDP消息传送有单播、广播、组播三种。
单播模式:一个UDP客户端发出的数据报只发送到另一个指定的地址和端口的UDP客户端,是一对一数据传输
广播模式:一个UDP客户端发出的数据报,在同一网络范围内其他所有的UDP客户端都可以接收到。QUdpSocket支持IPv4广播。广播经常用于实现网络发现的协议。要获取广播数据只需要将数据报发送到特定的接收端地址QHostAddress::Broadcast(255.255.255.255)
组播模式:也称为多播。UDP客户端加入到另一个组播IP地址指定的多播组(QUdpSocket::joinMuliticastGroup()),成员想组播地址发送的数据报组内成员都可以接收到,类似于QQ群的功能。一般即时通信都是基于UDP通信的。
代码实现:
udpsender: sender.h

#ifndef SENDER_H
#define SENDER_H
 
#include <QDialog>
class QUdpSocket;
 
namespace Ui {
class Sender;
}
 
class Sender : public QDialog
{
    Q_OBJECT
 
public:
    explicit Sender(QWidget *parent = 0);
    ~Sender();
 
private slots:
    void on_pushButton_clicked();// 发送数据报
 
private:
    Ui::Sender *ui;
    QUdpSocket *sender;
};
 
#endif // SENDER_H

udpsender: sender.cpp

#include "sender.h"
#include "ui_sender.h"
#include <QtNetwork>
 
Sender::Sender(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Sender)
{
    ui->setupUi(this);
    sender = new QUdpSocket(this);
}
 
Sender::~Sender()
{
    delete ui;
}
 
void Sender::on_pushButton_clicked()
{
    QByteArray datagram = "hello world!";
    //调用writeDatagram函数来发送数据(点对点消息和广播消息都适用)
    sender->writeDatagram(datagram.data(), datagram.size(),
                          QHostAddress::Broadcast, 45454);
 
}

udpreceiver: receiver.h

#ifndef RECEIVER_H
#define RECEIVER_H
 
#include <QDialog>
class QUdpSocket;
namespace Ui {
class Receiver;
}
 
class Receiver : public QDialog
{
    Q_OBJECT
 
public:
    explicit Receiver(QWidget *parent = 0);
    ~Receiver();
 
private:
    Ui::Receiver *ui;
    QUdpSocket *receiver;
 
private slots:
    void processPendingDatagram();// 读取接收到的数据报 
};
 
#endif // RECEIVER_H

udpreceiver: receiver.cpp

#include "receiver.h"
#include "ui_receiver.h"
#include <QtNetwork>
 
Receiver::Receiver(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Receiver)
{
    ui->setupUi(this);
 
    receiver = new QUdpSocket(this);
    // 要实现UDP数据的接收,必须先要bind一个端口,用于监听传入的数据报,解除用about函数.
    receiver->bind(45454, QUdpSocket::ShareAddress);
    // QUdpSocket接收到数据报后发射readyRead()信号,在关联的槽函数processPendingDatagram里读取缓冲区的数据报.
    connect(receiver, &QUdpSocket::readyRead, this, &Receiver::processPendingDatagram); 
}
 
Receiver::~Receiver()
{
    delete ui;
}
 
void Receiver::processPendingDatagram()
{
    // 拥有等待的数据报
    while(receiver->hasPendingDatagrams())
    {
        QByteArray datagram;
 
        // 让datagram的大小为等待处理的数据报的大小,这样才能接收到完整的数据
        datagram.resize(receiver->pendingDatagramSize());
 
        // 接收数据报,将其存放到datagram中
        receiver->readDatagram(datagram.data(), datagram.size());
        ui->label->setText(datagram);
    }
}
//hasPendingDatagrams表示是否有待读取的传入数据报
//pendingDatagramSize返回待读取数据报的字节数
//readDatagram用于读取数据报的内容.

猜你喜欢

转载自blog.csdn.net/QIJINGBO123/article/details/88617378