QT Udp广播实现设备发现

作者 : admin 本文共4783个字,预计阅读时间需要12分钟 发布时间: 2024-06-10 共2人阅读

测试环境

本文选用pc1作为客户端,pc2,以及一台虚拟机作为服务端

  • pc1,pc2(客户端):
    QT Udp广播实现设备发现插图
  • 虚拟机(服务端):
    QT Udp广播实现设备发现插图(1)

客户端

  • 原理:客户端通过发送广播消息信息到ip:255.255.255.255(QHostAddress::Broadcast),局域网内的所有设备收到该消息回复客户端即可。客户端通过收到的回复统计当前有哪些设备在线
  • 获取到本地的IP,getLocalIP函数获取到过滤了虚拟机网卡以及本地回环网卡后的ip地址。
    QT Udp广播实现设备发现插图(2)
#include "udpclient.h"
#include 
#include 
#include 
#include 
udpClient::udpClient(QObject *parent) : QObject(parent)
{
QString localIp = getLocalIP();
udpSocket = new QUdpSocket;
udpSocket->bind(QHostAddress(localIp),2001);
connect(udpSocket,&QUdpSocket::readyRead,this,&udpClient::processData);
}
QString udpClient::getLocalIP() {
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
foreach (const QNetworkInterface &interface, interfaces) {
QList<QNetworkAddressEntry> entries = interface.addressEntries();
qDebug()<<"name:"<<interface.humanReadableName()<<endl;
if(interface.humanReadableName().contains("Loopback") ||
interface.humanReadableName().contains("VMware Network Adapter"))
{
continue;
}
foreach (const QNetworkAddressEntry &entry, entries) {
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
qDebug() << "Local IP Address: " << entry.ip().toString()<< endl;
}
}
}
return QString();
}
udpClient::~udpClient()
{
if(udpSocket)
{
delete udpSocket;
}
}
void udpClient::sendBroadCast()
{
QByteArray datagram = "Device Discovery";
udpSocket->writeDatagram(datagram,QHostAddress::Broadcast,8888);
}
void udpClient::processData()
{
while(udpSocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
qDebug() << "Received response from: " << sender.toString()<<"port:"<<senderPort << endl;
}
}

服务端

#include "udpserver.h"
#include 
udpServer::udpServer(QObject *parent) : QObject(parent)
{
udpSocket = new QUdpSocket(this);
udpSocket->bind(QHostAddress::Any, 8888);
connect(udpSocket, &QUdpSocket::readyRead, this, &udpServer::processPendingDatagrams);
}
void udpServer::processPendingDatagrams()
{
while (udpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
std::cout << "Received discovery message: " << datagram.data() << std::endl;
QByteArray response = "Device Found";
udpSocket->writeDatagram(response, sender, senderPort);
}
}

输出效果

QT Udp广播实现设备发现插图(3)
QT Udp广播实现设备发现插图(4)

优化

  • 对客户端增加定时器,同时将客户端对象移动到一个线程中,这样就可以定时轮询设备发现了。
#include "udpclient.h"
#include 
#include 
#include 
#include 
#include 
#include 
udpClient::udpClient(QObject *parent) : QObject(parent)
{
qDebug()<<"thread id1:"<<QThread::currentThreadId()<<endl;
}
void udpClient::createSocket()
{
qDebug()<<"thread id2:"<<QThread::currentThreadId()<<endl;
QString localIp = getLocalIP();
udpSocket = new QUdpSocket;
udpSocket->bind(QHostAddress(localIp),2001);
connect(udpSocket,&QUdpSocket::readyRead,this,&udpClient::processData);
}
QString udpClient::getLocalIP() {
QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
foreach (const QNetworkInterface &interface, interfaces) {
QList<QNetworkAddressEntry> entries = interface.addressEntries();
qDebug()<<"name:"<<interface.humanReadableName()<<endl;
if(interface.humanReadableName().contains("Loopback") ||
interface.humanReadableName().contains("VMware Network Adapter"))
{
continue;
}
foreach (const QNetworkAddressEntry &entry, entries) {
if (entry.ip().protocol() == QAbstractSocket::IPv4Protocol) {
qDebug() << "Local IP Address: " << entry.ip().toString()<< endl;
}
}
}
return QString();
}
udpClient::~udpClient()
{
if(udpSocket)
{
delete udpSocket;
}
}
void udpClient::sendBroadCast()
{
QByteArray datagram = "Device Discovery";
udpSocket->writeDatagram(datagram,QHostAddress::Broadcast,8888);
qDebug()<<"sendBroadCast,thread id:"<<QThread::currentThreadId()<<endl;
}
void udpClient::processData()
{
while(udpSocket->hasPendingDatagrams())
{
QByteArray datagram;
datagram.resize(udpSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
udpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
result.push_back(IpInfo(sender.toString(),senderPort));
qDebug() << "Received response from: " << sender.toString()<<"port:"<<senderPort << endl;
}
}
void tcpConnect(QString& ip, quint16 port)
{
}
#include "widget.h"
#include "ui_widget.h"
#include 
#include 
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
client = new udpClient;
connect(ui->pushButton,&QPushButton::clicked,client,&udpClient::sendBroadCast);
thread = new QThread;
connect(thread,&QThread::finished,client,&QObject::deleteLater);
connect(thread,&QThread::started,client,&udpClient::createSocket);
client->moveToThread(thread);
timer = new QTimer(this);
connect(timer,&QTimer::timeout,client,&udpClient::sendBroadCast);
timer->setInterval(500);
thread->start();
//    QEventLoop loop;
//    QTimer::singleShot(500,&loop,&QEventLoop::quit);
//    loop.exec();
timer->start();
qDebug()<<"thread id:"<<QThread::currentThreadId()<<endl;
}
Widget::~Widget()
{
delete ui;
thread->quit();
thread->wait();
delete thread;
thread=nullptr;
}
本站无任何商业行为
个人在线分享 » QT Udp广播实现设备发现
E-->