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