赞
踩
最近由于工作需要,需要用Qt写一个udp通信的程序,这个udp程序只用来接收数据,不发送(等之后需要发送数据了在进行补充)于是就有了下面一个程序,我先将功能部分拆解,然后之后会将所有的源码放在下面,有需要的可以直接拷贝到下面,写这篇文章主要是为了分享给有需要的人,同时也记录下来方便自己以后回忆。
点击连接网络,会将本地的IP自动分配一个,然后建立连接,此时状态会显示建立udp连接成功,同时会在本地文件夹中生成一个
.log文件,这个文件作为日志文件,之后会将接收的数据放到log日志文件中去。清空显示则是清空接收。 接收计数则是显示接收的数据数量(具体的数据格式与数量之间的关系自己去算一下吧~)
因为工作需要,需要判断一些错误,将含有ERR的字符串设置为红色,其余设置为绿色。
QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size(), &address, &port); tmpIPPort =QHostAddress(address.toIPv4Address()).toString()+ ":" + QString::number(port, 10); QString rcvMsg = QString::fromUtf8(datagram, datagram.size()); if(CurIPPort != tmpIPPort) { CurIPPort = tmpIPPort; // if(ui->ReceiveTextEdit->toPlainText().size() == 0) { // ui->ReceiveTextEdit->moveCursor(QTextCursor::Start); // } // 设置文本颜色 QTextCharFormat fmt; fmt.setForeground(Qt::green); ui->ReceiveTextEdit->mergeCurrentCharFormat(fmt); ui->ReceiveTextEdit->appendPlainText(tr("【数据来自") + CurIPPort + tr("】")+"\n"); //添加数据 192.~ rcvDataCnt += datagram.size(); ui->lEdit_RcvCnt->setText(QString::number(rcvDataCnt, 10)); } // // 设置文本颜色 // QTextCharFormat fmt; // fmt.setForeground(Qt::green); int index = 0; QTextCharFormat fmt; while(index<rcvMsg.size()){ if(rcvMsg.mid(index).toLower().contains("err")){ fmt.setForeground(Qt::red); // qDebug()<<"进入红色"; break; } else{ fmt.setForeground(Qt::green); // qDebug()<<"进入绿色"; } index++; } if(ui->ReceiveTextEdit->toPlainText().size() == 0) { ui->ReceiveTextEdit->moveCursor(QTextCursor::Start); ui->ReceiveTextEdit->mergeCurrentCharFormat(fmt); ui->ReceiveTextEdit->insertPlainText(rcvMsg); // qDebug()<<rcvMsg; }else{ // 插入文本 ui->ReceiveTextEdit->moveCursor(QTextCursor::End); ui->ReceiveTextEdit->mergeCurrentCharFormat(fmt); ui->ReceiveTextEdit->insertPlainText(rcvMsg); }
在我们使用plaintextedit的insertPlainText方法的时候有时候鼠标光标移动会让内容错行,虽然可以使用appendPlainText方法防止移动,但是append方法会自动换行,这就让人很是难受,所以需要通过设置方法来设置这些问题。
//在界面初始化的时候将plaintextedit设置成这个
ui->ReceiveTextEdit->ensureCursorVisible();
ui->ReceiveTextEdit->setReadOnly(true);
用光标这样会有一个Bug就是在你使用clear方法的时候,你在接收数据界面是不会显示的,就很让人难过,于是我通过在使用clear方法之后重新设置一下光标就可以了。
.log文件
#------------------------------------------------- # # Project created by QtCreator 2014-04-10T19:21:07 # #------------------------------------------------- QT += core gui greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = NetAssistant target.path=/usr/local/bin INSTALLS=target TEMPLATE = app SOURCES += main.cpp\ mainwindow.cpp HEADERS += \ define.h \ mainwindow.h FORMS += \ mainwindow.ui RESOURCES += \ qrc.qrc QT +=network RC_FILE += icon.rc DISTFILES += \ android/AndroidManifest.xml TRANSLATIONS += language/English.ts \ language/Chinese.ts ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QtNetwork> #include <QDataStream> #include <QTextStream> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void setUdpGuiExt(); void setTcpSvrGuiExt(); void setTcpClientGuiExt(); QList<int> tcpClientSocketDescriptorList; int TcpClientLinkCnt; QString logFilePath; signals: void sendDataToClient(char *msg, int length, int socketDescriptor, int socketDescriptorEx); private slots: void on_pBtnNetCnnt_clicked(bool checked); void on_pBtnResetCnt_clicked(); char ConvertHexChar(char ch); char ConvertHexStr(QString hexSubStr); //=======UDP======== void udpDataReceived(); void on_pushButton_clicked(); private: Ui::MainWindow *ui; QString m_ip; //-----UDP----- QUdpSocket *udpSocket; QHostAddress lhAddr; int lhPort; QHostAddress rmtAddr; int rmtPort; //Global state unsigned int rcvDataCnt; unsigned int sndDataCnt; //bool NetState; QTimer *timer; bool loopSending; QString CurIPPort; QString CurPath; QFile *curFile; QTranslator translator; }; #endif // MAINWINDOW_H
#include "mainwindow.h" #include "ui_mainwindow.h" #include <QTranslator> #include "define.h" #include <QMessageBox> #include <stdlib.h> #include <QString> #include <QTimer> #include <QInputDialog> #include <QDateTime> #include <QFile> #include <QDateTime> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->ReceiveTextEdit->ensureCursorVisible(); ui->ReceiveTextEdit->setReadOnly(true); //设置程序的开启默认画面 setUdpGuiExt(); /*创建.log文件*/ QString logFileName = "logfile.log"; // 日志文件名 // 获取当前应用程序所在的目录 QString currentPath = QCoreApplication::applicationDirPath(); // 拼接日志文件的完整路径 logFilePath = currentPath + "/" + logFileName; if (!QFile::exists(logFilePath)) { QFile logFile(logFilePath); if (logFile.open(QIODevice::WriteOnly | QIODevice::Text)) { logFile.close(); ui->label->setText("日志文件已生成"); qDebug() << "Log file created."; } else { ui->label->setText("日志文件生成失败"); qDebug() << "Failed to create log file."; // 处理文件创建失败的情况 } } else{ ui->label->setText("日志文件已存在"); } //获取本机的IP地址,并初始化相应的控件属性和变量 QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses(); // use the first non-localhost IPv4 address for(int i = 0; i < ipAddressesList.size(); ++i) { if(ipAddressesList.at(i) != QHostAddress::LocalHost && ipAddressesList.at(i).toIPv4Address()) { m_ip = ipAddressesList.at(i).toString(); break; } } // 设置获取的IP到相应文本框 //ui->lEditIpAddr->setText(m_ip); // ui->lEditUdpIP->setText(m_ip); //初始化全局变量 rcvDataCnt = 0; sndDataCnt = 0; TcpClientLinkCnt = 0; //NetState = false; loopSending = false; CurIPPort = ""; CurPath = ""; curFile = 0; } MainWindow::~MainWindow() { delete ui; } /**********************************************************/ //Function for connection button void MainWindow::on_pBtnNetCnnt_clicked(bool checked) { if(checked) { //切换到链接状态 //建立UDP链接 udpSocket = new QUdpSocket(this); connect(udpSocket, SIGNAL(readyRead()), this, SLOT(udpDataReceived())); lhAddr.setAddress(m_ip); lhPort =1686; rmtAddr.setAddress("192.168.1.16"); rmtPort = 1689; bool result = udpSocket->bind(lhPort); if(!result) { ui->pBtnNetCnnt->setChecked(0); QMessageBox::information(this, tr("错误"), tr("UDP绑定端口失败!")); return; } ui->CurState->setText(tr("建立UDP连接成功")); ui->pBtnNetCnnt->setText(tr("断开网络")); //NetState = true; } else { //切换到断开状态 //断开UDP链接 udpSocket->close(); delete udpSocket; ui->pBtnNetCnnt->setText(tr("连接网络")); ui->CurState->setText(tr("")); // NetState = false; } } /**********************************************************/ //set UDP mode void MainWindow::setUdpGuiExt() { // ui->labelSpaceUdp->setVisible(true); // ui->lEditUdpIP->setVisible(true); // ui->labelUdp->setVisible(true); // ui->labelUdp1->setVisible(true); // ui->lEditUdpPort->setVisible(true); // ui->labelSpaceClients->setVisible(false); } /**********************************************************/ //udp data received void MainWindow::udpDataReceived() { QHostAddress address; quint16 port; QString tmpIPPort = ""; while(udpSocket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(udpSocket->pendingDatagramSize()); udpSocket->readDatagram(datagram.data(), datagram.size(), &address, &port); tmpIPPort =QHostAddress(address.toIPv4Address()).toString()+ ":" + QString::number(port, 10); QString rcvMsg = QString::fromUtf8(datagram, datagram.size()); if(CurIPPort != tmpIPPort) { CurIPPort = tmpIPPort; // if(ui->ReceiveTextEdit->toPlainText().size() == 0) { // ui->ReceiveTextEdit->moveCursor(QTextCursor::Start); // } // 设置文本颜色 QTextCharFormat fmt; fmt.setForeground(Qt::green); ui->ReceiveTextEdit->mergeCurrentCharFormat(fmt); ui->ReceiveTextEdit->appendPlainText(tr("【数据来自") + CurIPPort + tr("】")+"\n"); //添加数据 192.~ rcvDataCnt += datagram.size(); ui->lEdit_RcvCnt->setText(QString::number(rcvDataCnt, 10)); } // // 设置文本颜色 // QTextCharFormat fmt; // fmt.setForeground(Qt::green); int index = 0; QTextCharFormat fmt; while(index<rcvMsg.size()){ if(rcvMsg.mid(index).toLower().contains("err")){ fmt.setForeground(Qt::red); // qDebug()<<"进入红色"; break; } else{ fmt.setForeground(Qt::green); // qDebug()<<"进入绿色"; } index++; } if(ui->ReceiveTextEdit->toPlainText().size() == 0) { ui->ReceiveTextEdit->moveCursor(QTextCursor::Start); ui->ReceiveTextEdit->mergeCurrentCharFormat(fmt); ui->ReceiveTextEdit->insertPlainText(rcvMsg); // qDebug()<<rcvMsg; }else{ // 插入文本 ui->ReceiveTextEdit->moveCursor(QTextCursor::End); ui->ReceiveTextEdit->mergeCurrentCharFormat(fmt); ui->ReceiveTextEdit->insertPlainText(rcvMsg); } /*输出到.log文件中*/ QFile logFile(logFilePath); if (logFile.open(QIODevice::Append | QIODevice::Text)) { QTextStream logStream(&logFile); logStream << QDateTime::currentDateTime().toString("[yyyy-MM-dd hh:mm:ss] ") << rcvMsg ; logFile.close(); } else { qDebug() << "Failed to open log file for writing."; // 处理日志文件写入失败的情况 } // ui->ReceiveTextEdit->insertPlainText(rcvMsg); // ui->ReceiveTextEdit->appendPlainText(rcvMsg); //ui->ReceiveTextEdit->insertPlainText("\n"); //ui->ReceiveTextEdit->ensureCursorVisible(); //接收计数增加 rcvDataCnt += datagram.size(); ui->lEdit_RcvCnt->setText(QString::number(rcvDataCnt, 10)); } } /**********************************************************/ //reset the conters void MainWindow::on_pBtnResetCnt_clicked() { sndDataCnt = 0; rcvDataCnt = 0; ui->lEdit_RcvCnt->setText(QString::number(0, 10)); } /***********************************************/ //转化十六进制中的字符到ASCII char MainWindow::ConvertHexChar(char ch) { if((ch >= '0') && (ch <= '9')) return ch - 0x30; else if((ch >= 'A') && (ch <= 'F')) return ch - 'A' + 10; else if((ch >= 'a') && (ch <= 'f')) return ch - 'a' + 10; else return (-1); } /***********************************************/ //转化十六进制字符到ASCII字母 char MainWindow::ConvertHexStr(QString hexSubStr) { char ch = 0; if(hexSubStr.length() == 2) { // ch = ConvertHexChar(hexSubStr.at(0).toAscii())*16+ ConvertHexChar(hexSubStr.at(1).toAscii()); //qt4.8 ch = ConvertHexChar(hexSubStr.at(0).toLatin1()) * 16 + ConvertHexChar(hexSubStr.at(1).toLatin1()); } else if(hexSubStr.length() == 1) { //ch = ConvertHexChar(hexSubStr.at(0).toAscii()); //qt4.8 ch = ConvertHexChar(hexSubStr.at(0).toLatin1()); } return ch; } void MainWindow::on_pushButton_clicked() { ui->ReceiveTextEdit->clear(); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。