QT:UDP网络编程实现

QT UDP编程

QUdpSocket  UDP套接字   -  More.... 里面的Example伪代码
读写操作在成员函数内。

void QIODevice::readyRead ( );   // 适用于所有I/O通信

/** assistant 伪代码演示 **/

void Server::initSocket ( ) {
 // 创建UDP套接字
    udpSocket = new QUdpSocket (this);
 // 绑定
    udpSocket->bind (QHostAddress::LocalHost, 7755);
 // 当套接字有数据时会发送 readyRead ( )
    connect (udpSocket, SIGNAL (readyRead( )), this, SLOT (readPendingDatagrams( )));
}
void Server::readPendingDatagrams ( ) {
 // 判断当前套接字是否有数据包到来
 while (udpSocket->hasPendingDatagrams ( )) {
  // 数据缓冲区,类似 char [ ]
        QByteArray datagram;
  // 获取当前数据包的大小,从到来的套接字数据包
        datagram.resize (udpSocket->pendingDatagramSize ( ));
        QHostAddress sender;  // 保存客户端的IP地址
        quint16 senderPort;  // 保存客户端的端口号
  // 读取数据,.data ( )完成的是数据类型转换为 char *
        udpSocket->readDatagram (datagram.data ( ), datagram.size ( ), &sender, &senderPort);
  // 解析和处理...
        processTheDatagram (datagram);
    }
}

《案例》UDP网络广播
1 )发送广播地址
 指定广播地址:255.255.255.255  ' QHostAddress::Broadcast '
 // enum QHostAddress::SpecialAddress
 指定广播端口:8888
 通过定时器,每隔1s广播1条消息
mkdir UdpBroadcast
工程名:UdpSender
类名:UdpSenderDialog
UdpSender.pro   --->   QT += network

2 )接收广播消息
 绑定接收的端口号
 接收广播消息,并显示
工程名:UdpReceiver
类名:UdpReceiverDialog
UdpReceiver.pro  --->  QT += network


/* 发送广播地址 - 代码演示 */

// UdpSenderDialog.h
#ifndef UDPSENDERDIALOG_H
#define UDPSENDERDIALOG_H
#include <QDialog>
#include <QUdpSocket>
#include <QTimer> // 定时器
namespace Ui {
class UdpSenderDialog;
}
class UdpSenderDialog : public QDialog {
    Q_OBJECT
public:
    explicit UdpSenderDialog(QWidget *parent = 0);
    ~UdpSenderDialog();
private slots:
    void on_startButton_clicked();
    // 定时器到时后发送信息的槽函数
    void sendMessage (void);
private:
    Ui::UdpSenderDialog *ui;
    bool isStarted; // 判断是否已经开始广播
    QUdpSocket* udpSocket;
    QTimer* timer; // 定时器,定时广播消息
};
#endif // UDPSENDERDIALOG_H

// UdpSenderDialog.cpp
#include "UdpSenderDialog.h"
#include "ui_UdpSenderDialog.h"
UdpSenderDialog::UdpSenderDialog (QWidget *parent) :
    QDialog (parent),
    ui(new Ui::UdpSenderDialog) {
    ui->setupUi (this);
    isStarted = false;
    udpSocket = new QUdpSocket (this);
    timer = new QTimer (this);
    // 定时器到时以后发送timeout ()信号
    connect (timer, SIGNAL (timeout ()), this, SLOT (sendMessage ()));
}
UdpSenderDialog::~UdpSenderDialog () {
    delete ui;
}
void UdpSenderDialog::on_startButton_clicked () {
    if (isStarted == false) {
        // 开始广播
        isStarted = true;
        ui->startButton->setText ("停止广播");
        // 禁用广播端口和消息输入的组件
        ui->portEdit->setEnabled (false);
        ui->messageEdit->setEnabled (false);
        // 开启定时器,每隔1s广播一次
        timer->start (100);
    }
    else {
        // 停止广播
        isStarted = false;
        ui->startButton->setText ("开始广播");
        ui->portEdit->setEnabled (true);
        ui->messageEdit->setEnabled (true);
        // 停止定时器
        timer->stop ();
    }
}
// 定时器到时后发送消息的槽函数
void UdpSenderDialog::sendMessage (void) {
    // 获取端口号和广播的消息
    quint16 port = ui->portEdit->text ().toShort ();
    QString msg = ui->messageEdit->text ();
    // 发送消息到广播地址 "255.255.255.255"
    // toLocal8Bit ():QString ===> QByteArray
    udpSocket->writeDatagram (msg.toLocal8Bit (), QHostAddress::Broadcast, port);
    qDebug () << msg;
}
// main.cpp
#include "UdpSenderDialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    UdpSenderDialog w;
    w.show();
    return a.exec();
}


/* 接收广播消息 */

// UdpReceiverDialog.h
#ifndef UDPRECEIVERDIALOG_H
#define UDPRECEIVERDIALOG_H
#include <QDialog>
#include <QUdpSocket>
#include <QMessageBox>
namespace Ui {
class UdpReceiverDialog;
}
class UdpReceiverDialog : public QDialog {
    Q_OBJECT
public:
    explicit UdpReceiverDialog(QWidget *parent = 0);
    ~UdpReceiverDialog();
private slots:
    void on_startButton_clicked();
    // 当套接字有数据到来,接收数据的槽函数
    void messageReceived ();
    void on_clearButton_clicked();
private:
    Ui::UdpReceiverDialog *ui;
    QUdpSocket* udpSocket;
    quint16 port; // == unsigned short
    bool isStarted; // 标记是否开始接收
};
#endif // UDPRECEIVERDIALOG_H

// UdpReceiverDialog.cpp
#include "UdpReceiverDialog.h"
#include "ui_UdpReceiverDialog.h"
UdpReceiverDialog::UdpReceiverDialog (QWidget *parent) :
    QDialog (parent),
    ui (new Ui::UdpReceiverDialog) {
    ui->setupUi (this);
    udpSocket = new QUdpSocket (this);
    isStarted = false;
}
UdpReceiverDialog::~UdpReceiverDialog () {
    delete ui;
}
void UdpReceiverDialog::on_startButton_clicked() {
    if (isStarted == false) {
        // 开始接收广播消息
        isStarted = true;
        // 获取和绑定接收消息的端口号
        port = ui->portEdit->text ().toShort ();
        bool res = udpSocket->bind (port);
        if (res == false) {
            // 弹出错误提示消息框
            QMessageBox::information (this, "Error", "Udp bind error!");
            return ;
        }
        // 禁用输入组件
        ui->portEdit->setEnabled (false);
        // 开始按钮内容改为停止接收
        ui->startButton->setText ("停止接收");
        // 监听套接字有数据发来时,将会发送信号 readyRead
        connect (udpSocket, SIGNAL (readyRead ()), this, SLOT (messageReceived ()));
    }
    else {
        // 停止接收
        isStarted = false;
        // 关闭套接字
        udpSocket->close ();
        // 使能输入组件
        ui->portEdit->setEnabled (true);
        // 停止按钮内容改为开始接收
        ui->startButton->setText ("开始接收");
    }
}
// 当套接字有数据到来,接收数据的槽函数
void UdpReceiverDialog::messageReceived () {
    if (udpSocket->hasPendingDatagrams ()) {
        QByteArray datagram;
        datagram.resize (udpSocket->pendingDatagramSize ());
        // data ():QByteArray  ---> 转换为 char *
        // 接收消息
        udpSocket->readDatagram (datagram.data (), datagram.size ());
        // 显示消息
        ui->listWidget->addItem (datagram.data ());
    }
}
void UdpReceiverDialog::on_clearButton_clicked() {
    ui->listWidget->clear ();
}
// main.cpp
#include "UdpReceiverDialog.h"
#include <QApplication>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    UdpReceiverDialog w;
    w.show();
    return a.exec();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

姜源Jerry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值