一直想写博客但是太懒了。。。根据最近做项目用到的东西就写个UDP吧,希望对大家有所帮助,嗯,其他的以后想起来再写。
主要内容:qt作为客户端实现报文的收发,用定时器实现定时写(心跳包),可断开重新连接。
测试别忘记关掉防火墙。
以下代码是简化过的,仅供参考,如有不当之处,欢迎指正。
下载链接(永久有效,失效请评论):
链接:https://pan.baidu.com/s/1aFmmJdO6s5QcRcSyIZysYA
提取码:a3nk
clent界面:
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); }