Qt开发的UDP接收端

    上一篇已经说完了简单UDP发送端开发,参见我的博客:Qt开发的UDP发送端。

    博文地址:https://my.oschina.net/marshal2bit/blog/803803

    做完UDP发送端,我又尝试做了一个UDP接收端。先上图,做出来的样子如下:

    170943_iQrT_2936888.png

    一、开发环境(和上篇博文一样)

    系统:Windows 7 专业版(64位)

    软件:qt-opensource-windows-x86-mingw530-5.7.0(原来用Qt 5.2.1+完成的工程)

    注:Qt下载链接http://download.qt.io/official_releases/qt/

    二、新建工程

    见文章开头的博客链接。注意修改.pro文件  

#-------------------------------------------------
#
# Project created by QtCreator 2016-12-03T18:32:29
#
#-------------------------------------------------

QT       += core gui network

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = udpEndpoint2
TEMPLATE = app


SOURCES += main.cpp\
        widget.cpp

HEADERS  += widget.h

FORMS    += widget.ui

    新建好的工程界面如下:

    171406_z1fg_2936888.png

    三、设计ui界面

    进入“widget.ui”,设计如下界面:

    171307_JWm7_2936888.png

控件信息见下表:  

控件标号控件类别控件名称(objectName)
1QLabellabel_4
2QLineEditlineEdit
3QLabellabel
4QTextBrowserdataRecv
5QLabellabel_2
6QTextBrowserfromIP
7QLabellabel_3
8QTextBrowserfromPort
9QPushButtonpushButton

    四、ui界面的“信号-槽”函数设置

    172322_mnYB_2936888.png

    五、代码编辑

    (一)编辑“widget.h”,编辑如下:

//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QtNetwork/QUdpSocket>

namespace Ui {
class Widget;
}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void processPendingDatagram();
    void on_pushButton_clicked();

    void on_lineEdit_editingFinished();

private:
    QUdpSocket *receiver;
    Ui::Widget *ui;
};

#endif // WIDGET_H

(二)编辑“widget.cpp”,如下:

//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "QtNetwork/QUdpSocket"
#include "QtNetwork/QHostAddress"
#include "QTextCodec"

QRegExp regExpIP("((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])[\\.]){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])");
QRegExp regExpNetPort("((6553[0-5])|[655[0-2][0-9]|65[0-4][0-9]{2}|6[0-4][0-9]{3}|[1-5][0-9]{4}|[1-9][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[0-9])");
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    this->setWindowTitle("UDP接收端");
    ui->lineEdit->setValidator\
            (new QRegExpValidator(regExpNetPort,this));
    ui->label->setText("等待接收数据……");
    ui->pushButton->setText("清空");

    receiver = new QUdpSocket(this);
    //receiver->bind(8083);  //端口8083接收
    connect(receiver,SIGNAL(readyRead()),this,SLOT(processPendingDatagram()));
}
//接收数据
void Widget::processPendingDatagram()
{
    QHostAddress *sourceIP = new QHostAddress();
    quint16 sourcePort;
    while(receiver->hasPendingDatagrams())
    {
        QByteArray datagram;
        QString dataStr;

        QTextCodec *tutf=QTextCodec::codecForName("UTF-8");  //显示中文
        datagram.resize(receiver->pendingDatagramSize());
        receiver->readDatagram(datagram.data(),datagram.size(),\
                               sourceIP,&sourcePort);    //接收
        dataStr = tutf->toUnicode(datagram);  //接收数据格式化以便于中文显示
        ui->label->setText("接收到的数据");
        //ui->dataRecv->setText(dataStr);
        ui->dataRecv->append(dataStr);
        ui->fromIP->setText(sourceIP->toString());  //查看数据源IP地址
        ui->fromPort->setText(QString::number(sourcePort, 10));  //查看数据源端口
    }
    delete sourceIP;
}
Widget::~Widget()
{
    delete ui;
}

//清空数据
void Widget::on_pushButton_clicked()
{
    if(ui->label->text() == "接收到的数据")
        ui->label->setText("已清空,等待新数据到来……");
}

void Widget::on_lineEdit_editingFinished()
{
    QString inputPort = ui->lineEdit->text();
    quint16 local_port;
    receiver->abort();   //复位socket
    //处理端口输入
    if(inputPort.isEmpty())
        local_port = -1;
    else
        local_port = inputPort.toUInt();   //QString 文本输入,转换为quint16的数字端口
    receiver->bind(local_port);     //绑定输入端口
}

main.cpp”无需修改

//main.cpp
#include "widget.h"
#include <QApplication>
#include <QTextCodec>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    //QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    w.show();
    return a.exec();
}

六、程序运行

运行界面如文章开头所示,使用实例与开头所提的博客对应。

用8083端口接收本机8082发送端发过来的数据,本机IP:10.56.195.19。运行前设置

182225_4xLD_2936888.png

点击发送后,运行结果

182255_NfbN_2936888.png

    在Qt 5.2.1中,源IP只显示IP地址:10.56.195.19,到了5.7.0不知道怎么会出来::ff:这个东西,有时间再看看,知道原因的博友也请指教指教。

    到此为止,UDP发送端和接收端开发已经讲完。

    (over)

转载于:https://my.oschina.net/marshal2bit/blog/804640

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Qt UDP 接收端限制接收速度的完整代码示例: ```cpp #include <QtWidgets> #include <QUdpSocket> class UdpReceiver : public QWidget { Q_OBJECT public: UdpReceiver(QWidget *parent = nullptr) : QWidget(parent) { setWindowTitle(tr("UDP Receiver")); // 创建 UDP socket udpSocket = new QUdpSocket(this); // 绑定 UDP socket 到本地端口 udpSocket->bind(QHostAddress::Any, 1234); // 设置接收缓冲区大小 udpSocket->setReadBufferSize(64 * 1024); // 开始接收数据 connect(udpSocket, &QUdpSocket::readyRead, this, &UdpReceiver::processPendingDatagrams); // 创建定时器,限制接收速度 receiveTimer = new QTimer(this); receiveTimer->setInterval(1000); // 每秒接收一次数据 connect(receiveTimer, &QTimer::timeout, this, &UdpReceiver::startReceiving); receiveTimer->start(); } private slots: void processPendingDatagrams() { while (udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size()); // 处理接收到的数据 // ... receivedBytes += datagram.size(); receivedDatagrams++; } } void startReceiving() { // 停止接收数据 udpSocket->disconnectFromHost(); // 输出接收速率 qDebug() << "Received" << receivedBytes << "bytes in" << receivedDatagrams << "datagrams (" << receivedBytes / receiveTimer->interval() << " B/s)"; // 重置接收计数器 receivedBytes = 0; receivedDatagrams = 0; // 开始接收数据 udpSocket->connectToHost(QHostAddress::Any, 1234); } private: QUdpSocket *udpSocket; QTimer *receiveTimer; qint64 receivedBytes = 0; qint64 receivedDatagrams = 0; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); UdpReceiver receiver; receiver.show(); return app.exec(); } #include "main.moc" ``` 此代码创建了一个 `QUdpSocket` 对象,并将其绑定到本地端口 `1234` 上。使用定时器限制接收速度,每秒最多接收一次数据。当接收到数据时,会输出接收速率,并重置接收计数器,以便下一个时间段内重新计算速率。 请注意,此示例中限制接收速度的方法是简单地断开并重新连接到 UDP 服务器,这可能会导致一些数据包丢失。更可靠的方法是在读取数据之前使用 `QUdpSocket::waitForReadyRead()` 等待足够的数据可用,以便在限制速率的同时保持接收所有数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值