一直想写博客但是太懒了。。。根据最近做项目用到的东西就写个UDP吧,希望对大家有所帮助,嗯,其他的以后想起来再写。
主要内容:qt作为客户端实现报文的收发,用定时器实现定时写(心跳包),可断开重新连接。
测试别忘记关掉防火墙。
以下代码是简化过的,仅供参考,如有不当之处,欢迎指正。
下载链接(永久有效,失效请评论):
链接:https://pan.baidu.com/s/1aFmmJdO6s5QcRcSyIZysYA? 提取码:a3nk
界面:
?UdpClient.pro
QT += core gui
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
SOURCES += \
main.cpp \
udpclient.cpp
HEADERS += \
udpclient.h
FORMS += \
udpclient.ui
QT += network
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
udpclient.h
#ifndef UDPCLIENT_H
#define UDPCLIENT_H
#include <QMainWindow>
#include <QUdpSocket>
QT_BEGIN_NAMESPACE
namespace Ui {
class UdpClient;
}
QT_END_NAMESPACE
class UdpClient : public QMainWindow {
Q_OBJECT
public:
UdpClient(QWidget *parent = nullptr);
~UdpClient();
private slots:
void on_connet_pushButton_clicked();
void sendData();
void readData();
void on_connect_pushButton_clicked();
private:
Ui::UdpClient *ui;
QUdpSocket *udpClient;
QString ip;
qint64 port;
qint64 reciveTime;
qint64 sendTime;
QTimer *writeTimer;
static const quint64 RESPONSE_INTERVAL;//write周期
static const quint64 HEARTBEAT_TIMEOUT;//超时未应答时间
bool isVaildIp(QString &ip);
void resetStatues();
bool btnStatues;
};
#endif // UDPCLIENT_H
?udpclient.cpp
#include "udpclient.h"
#include "ui_udpclient.h"
#include <QTimer>
#include <QMessageBox>
const quint64 UdpClient::RESPONSE_INTERVAL = 5; //s
const quint64 UdpClient::HEARTBEAT_TIMEOUT = 15; //s
UdpClient::UdpClient(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::UdpClient) {
ui->setupUi(this);
writeTimer = nullptr;
ip = "192.168.56.200";
port = 8888;
sendTime = 0;
reciveTime = 0;
btnStatues = false;
udpClient = new QUdpSocket(this);
udpClient->bind(QHostAddress(ip), QUdpSocket::ShareAddress);
QObject::connect(udpClient, SIGNAL(readyRead()), this, SLOT(readData()));
writeTimer = new QTimer;
QObject::connect(writeTimer, SIGNAL(timeout()), this, SLOT(sendData()));
}
UdpClient::~UdpClient() {
delete ui;
}
bool UdpClient::isVaildIp(QString &ip) {
QHostAddress test;
if (!test.setAddress(ip)) {
return false;
}
return true;
}
void UdpClient::sendData() {
quint64 now = time(NULL);
if ((now - sendTime) > RESPONSE_INTERVAL) {
udpClient->writeDatagram("{\"order\":\"HELLO\"}", QHostAddress(ip), port);
ui->send_lable->setText("HELLO");
#ifdef QT_DEBUG
qDebug() << "send: HELLO";
#endif
sendTime = now;
}
}
void UdpClient::readData() {
QByteArray arr;
quint64 now = time(NULL);
while(udpClient->hasPendingDatagrams()) {
arr.resize(udpClient->bytesAvailable());
udpClient->readDatagram(arr.data(), arr.size());
reciveTime = now;
#ifdef QT_DEBUG
qDebug() << "read: " << arr.data();
#endif
}
if (!strcmp(arr.data(), "HELLO")) {
ui->connect_pushButton->setText("断开");
btnStatues = true;
ui->recive_lable->setText(arr.data());
} else {
if(now - reciveTime > HEARTBEAT_TIMEOUT) {
ui->connect_pushButton->setText("连接");
btnStatues = false;
}
}
}
void UdpClient::resetStatues() {
sendTime = 0;
reciveTime = 0;
}
void UdpClient::on_connect_pushButton_clicked() {
if(!btnStatues) { //未连接
if(!isVaildIp(ip)) {
QMessageBox::warning(NULL, "提示", "IP地址不合法!", QMessageBox::Ok);
return;
}
} else {
udpClient->close();//必须关闭,不然无法重新绑定
resetStatues();
btnStatues = false;
writeTimer->stop();
ui->connect_pushButton->setText("连接");
return;
}
#ifdef QT_DEBUG
qDebug() << "connecting: " << ip << " port: " << port;
#endif
udpClient->bind(QHostAddress(ip), QUdpSocket::ShareAddress);
writeTimer->start(0);
}
|