QT5 UDP通信

  • Post author:
  • Post category:其他


QT版本:5.12.0

DUP通信


1、UDP通信概念

QUdpSocket类用于实现UDP通信,它从QAbstractSocket类继承,因而与QTcpSocket共享大部分的接口函数。主要区别是

QUdpSocket以数据包传输数据

,而不是连续的数据流。


发送数据包使用QUdpSocket::writeDataGram()

,数据包的长度一般少于512字节,每个数据报包含发送者和接受者的

IP地址



端口

等信息。

要进行UDP数据接收,

要用QUdpSocket::bind()函数先绑定一个端口

,用于接收传入的数据包。当有数据包传入时会发射

readRead()

信号,使用readDatagram()函数来读取接受到的数据报。


2、QHostAddress类提供一个IP地址。


3、QByteArray

Qt中无论是serialport、tcp、udp网络通信等,直接接收到(或者要发送)的数据都是QByteArray,之后的数据处理部分,无论转换为char*/ char[] 还是QString,都需要通过QByteArray转换而来。

QByteArray ba(24,0); 创建一个长度为24字节,初始值为0的字节数组。

访问QByteArray主要有4中方式,分别为[],at(),data[]和constData[]。其中[]和data[]为可读可写,at()和constData[]仅为可读,则通过at()和constData[]访问最快,因为可以避免复制处理。


4、.获取系统时间

    QDateTime currentDataTime=QDateTime::currentDateTime();
    QString currentData=currentDataTime.toString("yyyy-MM-dd hh:mm::ss.zzz");
    qDebug()<<"当前时刻:"<<currentData<<endl;
.cpp文件
#include "dialog.h"
#include "ui_dialog.h"

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
{
    ui->setupUi(this);
    this->initIniFile();

    m_qudpSocket=new QUdpSocket();

    //绑定接收端IP及端口
    m_qudpSocket->bind(QHostAddress(ui->label_objectIP->text()),ui->label_port->text().toInt());
    // m_qudpSocket->bind(QHostAddress(strIP),nport);
    connect(m_qudpSocket,SIGNAL(readyRead()),this,SLOT(recvData()));

}

void Dialog::initIniFile(){
    QString strCurrentAppDirPath=QApplication::applicationDirPath();
    qDebug()<<strCurrentAppDirPath<<endl;
    QString configFleName="config.ini";
    QString strFullFileName=strCurrentAppDirPath+"/"+configFleName;

    QSettings iniFileRead(strFullFileName,QSettings::IniFormat);

    QString inisendLogFile=iniFileRead.value("UDP/sendLogFile",QString("NULL")).toString();
    m_sendFileName=strCurrentAppDirPath+"/"+inisendLogFile;
    //    //发送者文件名
    //    qDebug()<<"发送者文件路径: "<<m_sendFileName<<endl;
    QString inireceiveLogFile=iniFileRead.value("UDP/receiveLogFile",QString("NULL")).toString();
    m_receiveFileName=strCurrentAppDirPath+"/"+inireceiveLogFile;
    //    qDebug()<<"接收者文件路径: "<<m_receiveFileName<<endl;

    QString objectPort=iniFileRead.value("UDP/objectPort").toString();
    ui->label_port->setText(objectPort);

    //    qDebug()<<"目标端口号: "<<objectPort<<endl;

    QString objIP=iniFileRead.value("UDP/objectIP").toString();
    ui->label_objectIP->setText(objIP);

}
Dialog::~Dialog()
{
    delete m_qudpSocket;
    delete ui;
}


void Dialog::recvData(){

    //测试时间
    QDateTime currentDataTime=QDateTime::currentDateTime();
    QString currentData=currentDataTime.toString("yyyy-MM-dd hh:mm::ss.zzz");
    //    qDebug()<<"当前时刻:"<<currentData<<endl;

    QFile recvContent(m_receiveFileName);
    if(!recvContent.exists()){
        recvContent.open(QIODevice::ReadWrite|QIODevice::Text);
        recvContent.close();
    }
    recvContent.open(QIODevice::Append);
    QTextStream recvOutput(&recvContent);

    recvOutput<<"sender  IP:127.0.0.1    port:8080"<<endl;
    recvOutput<<"recieve IP:127.0.0.1    port:8080"<<endl;
    recvOutput<<"receive time:"<<currentData<<endl;
    recvOutput<<"receive content"<<endl;
    QByteArray baRecv;
    //读取收到的数据报
    int i=0;
    while (m_qudpSocket->hasPendingDatagrams()) {
        /*
        hasPendingDatagrams() 表示是否有待读取的传入数据报

        pendingDatagramSize() 为返回第一个在等待读取报文的size,resize函数是把baRecv的size归一化到参数size的大小一样
        将读取到的不大于baRecv.size()大小数据输入到baRecv.data()中,baRecv.data()返回的是一个字节数组中存储数据位置的指针
        */
        baRecv.resize(m_qudpSocket->pendingDatagramSize());

        /*
        read readDatagram(char *data,qint64 maxSize);
        baRecv.data()   返回数据指针
        */
        m_qudpSocket->readDatagram(baRecv.data(),baRecv.size());
        QString strRecvData=baRecv;
        //        //文本框内容
        //        qDebug()<<"接收数据:"<<baRecv.data()<<endl<<endl;;

        ui->plainTextEdit->setPlainText(strRecvData);
        i++;
        qDebug()<<"接收命令次数:"<<i<<endl;
        recvOutput<<strRecvData<<endl;
        qDebug()<<baRecv.data();
    }
    recvOutput<<"receive  over -------------------------"<<endl;
    recvContent.close();
    //    qDebug()<<"******************break\n";

}
/*
 程序说明开始
功能:
将发送端文本框信息发送到接收端,在接收端文本框显示接收信息。
调用方法:
点击界面的send按钮调用改方法
*/
void Dialog::on_btnSend_clicked()
{

    /*
    ui->sendTextEdit->toPlainText().toUtf8()   数据转换为QByteArray

    writeDatagram(QByteArray &datagram,QHostAddress &host,quint16 port);
    */

    m_qudpSocket->writeDatagram(ui->sendTextEdit->toPlainText().toUtf8(),QHostAddress(ui->label_objectIP->text()),ui->label_port->text().toInt());

}
头文件
#ifndef DIALOG_H
#define DIALOG_H

#include <QDialog>
#include<QString>
#include<QApplication>
#include<QDebug>
#include<QSettings>
#include<QDateTime>
#include<QUdpSocket>
namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

public:
    explicit Dialog(QWidget *parent = nullptr);
    ~Dialog();
    //解析ini文件
    QString m_fileName;
    void initIniFile();
    QString m_sendFileName;
    QString m_receiveFileName;
    QUdpSocket *m_qudpSocket;

private slots:
    void recvData();
    void on_btnSend_clicked();

private:
    Ui::Dialog *ui;
};

#endif // DIALOG_H



版权声明:本文为g96889原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。