QT 通过UDP广播获取网络中所有设备ip地址

说明:

源码下载地址:http://download.csdn.net/detail/dxzysk/9756965

提供源码下载地址,源码使用说明,先在需要待搜索待获取IP地址的主机上运行server端程序,然后在需要查看搜索结果的主机的Pc上运行client端程序

本文是C++的QT版本例子说明,有时候需要搜索网络中的设备,机器,服务器等,这就要要用到UDP广播的方式,发送广播命令,广播给网络中的每一个主机,该主机接收到广播命令后,立刻发送给请求端自己的设备信息,这里以IP信息为例子。

思路

在每一个设备中部署sever端程序进行监控,client端发送广播命令,每一个server收到命令后,返回给client自己的ip地址信息,给出代码如下,其中,有部分,比如获取ip地址参考来自网络,尊重原创,乐于分享。

server端(QT版)

server端监听广播命令”GetIPAddr”,收到命令后就相应,本例中几面显示收到的广播命令和命令来源的ip地址

  • mainwindow.h
  #ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}
class QLabel;
class QUdpSocket;
class QListWidget;
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void initList();
    void addBroadcastResItem(QByteArray data, QString ip);
    void BroadcastGetIpCommand();
    void initBroadcastListener();
    QString getIp();
private:
    Ui::MainWindow *ui;
private:
    QLabel *label;
    QListWidget* mlistWidget;
       /////////////
    QUdpSocket * receiver;
    QUdpSocket * sender;
private slots:
    void processPengingDatagram();
    ///////////
};

#endif // MAINWINDOW_H

  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QtNetwork>
#include<QLabel>
#include <QListWidget>
#include <QVBoxLayout>
#include <QListWidgetItem>
//#define GET_HOST_COMMAND "GetCYHost"
#define GET_HOST_COMMAND "GetIPAddr"
//#define LOCAL_PORT 11121
#define Server_PORT 12811

#define TRY_TIMES 1

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle("Server");
    initList();
    ////////////////////////////////
    initBroadcastListener();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initBroadcastListener()
{
    receiver = new QUdpSocket(this);
    /////绑定,第一个参数为端口号,第二儿表示允许其它地址链接该广播
    receiver->bind(Server_PORT,QUdpSocket::ShareAddress);

    //readyRead:每当有数据报来时发送这个信号
    connect(receiver,SIGNAL(readyRead()),this,SLOT(processPengingDatagram()));

}


void MainWindow::initList()
{
    label = new QLabel;
    label->setFixedWidth(70);
    label->setText("收到的广播源:");
    mlistWidget = new QListWidget;
    QVBoxLayout* layout = new QVBoxLayout;
    QListWidgetItem* lst1 = new QListWidgetItem("broacast command and ip list:", mlistWidget);
    mlistWidget->insertItem(1, lst1);
    layout->addWidget(label);
    layout->addWidget(mlistWidget);


    QWidget *mainWidget = new QWidget;
    mainWidget->setLayout(layout);

    setCentralWidget(mainWidget);
}
void MainWindow::processPengingDatagram()
{
    QHostAddress client_address;//声明一个QHostAddress对象用于保存发送端的信息
    //char buf[100];//声明一个字符数组用于接收发送过来的字符串
    //数据报不为空
    while( receiver->hasPendingDatagrams() )
    {
        quint16 recPort = 0;
        QByteArray datagram;
        //datagram大小为等待处理数据报的大小才能就收数据;
        datagram.resize( receiver->pendingDatagramSize() );
        //接收数据报
        receiver->readDatagram(datagram.data(),datagram.size(), &client_address, &recPort);
        //label->setText(datagram);
        QString strData= datagram;
        int ret = strData.compare(GET_HOST_COMMAND);
        if (0 == ret)
        {
            addBroadcastResItem(datagram, client_address.toString());
            QByteArray datagback = "my ip is:"+getIp().toLatin1();
            //QByteArray datagback = "my ip is:192.168.1.123";//+getIp().toLatin1();
            receiver->writeDatagram(datagback,datagback.size(),client_address,recPort);
        }
    }
}

void MainWindow::addBroadcastResItem(QByteArray data, QString ip)
{

    QListWidgetItem* lst1 = new QListWidgetItem(data + "\t" + ip, mlistWidget);
    mlistWidget->insertItem(1, lst1);
}

//得到主机的ip地址
QString MainWindow::getIp()
{
 //使用allAddresses命令获得所有的ip地址
    QList<QHostAddress> list=QNetworkInterface::allAddresses();
    foreach (QHostAddress address,list)
    {
        if(address.protocol()==QAbstractSocket::IPv4Protocol)
            return address.toString();
    }
    return 0;
}

client端(QT版)

为了便于观察,我们把搜索到的Ip地址,在界面上显示出来,可以用MFC,我这里用QT代替了,感兴趣的同学可以用MFC练习一下。QT的代码如下:

  • mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

namespace Ui {
class MainWindow;
}
class QLabel;
class QUdpSocket;
class QListWidget;
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void initList();
    void addIpItem(QByteArray data);
    void BroadcastGetIpCommand();
    void initBroadcast();
private:
    Ui::MainWindow *ui;
private:
    QLabel *label;
    QListWidget* mlistWidget;
       /////////////
    QUdpSocket * receiver;
    QUdpSocket * sender;
private slots:
    void processPengingDatagram();
    ///////////
};

#endif // MAINWINDOW_H
  • mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QtNetwork>
#include<QLabel>
#include <QListWidget>
#include <QVBoxLayout>
#include <QListWidgetItem>
//#define GET_HOST_COMMAND "GetCYHost"
#define GET_HOST_COMMAND "GetIPAddr"
#define LOCAL_PORT 11121
#define DEST_PORT 12811

#define TRY_TIMES 1

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initList();
    ////////////////////////////////
    initBroadcast();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initBroadcast()
{
    receiver = new QUdpSocket(this);
    /////绑定,第一个参数为端口号,第二儿表示允许其它地址链接该广播
    receiver->bind(LOCAL_PORT,QUdpSocket::ShareAddress);

    //readyRead:每当有数据报来时发送这个信号
    connect(receiver,SIGNAL(readyRead()),this,SLOT(processPengingDatagram()));

    BroadcastGetIpCommand();
}

void MainWindow::BroadcastGetIpCommand()
{
    //QByteArray datagram = "Hello World!";
    QByteArray datagram = GET_HOST_COMMAND;
    int times = TRY_TIMES;
    while(times--)
    {
        //sender->writeDatagram(datagram.data(),datagram.size(),QHostAddress::Broadcast,1066);
        receiver->writeDatagram(datagram.data(),datagram.size(),QHostAddress::Broadcast,DEST_PORT);
    }
}

void MainWindow::initList()
{
    label = new QLabel;
    label->setFixedWidth(70);
    label->setText("广播IP地址:");
    mlistWidget = new QListWidget;
    QVBoxLayout* layout = new QVBoxLayout;
    QListWidgetItem* lst1 = new QListWidgetItem("ip list:", mlistWidget);

    mlistWidget->insertItem(1, lst1);

    //mlistWidget->show();
    layout->addWidget(label);
    layout->addWidget(mlistWidget);


    QWidget *mainWidget = new QWidget;
    mainWidget->setLayout(layout);

    setCentralWidget(mainWidget);
}

void MainWindow::processPengingDatagram()
{
    //数据报不为空
    while( receiver->hasPendingDatagrams() )
    {
        QByteArray datagram;
        //datagram大小为等待处理数据报的大小才能就收数据;
        datagram.resize( receiver->pendingDatagramSize() );
        //接收数据报
        receiver->readDatagram(datagram.data(),datagram.size());
        //label->setText(datagram);
        addIpItem(datagram);
    }
}

void MainWindow::addIpItem(QByteArray data)
{

    QListWidgetItem* lst1 = new QListWidgetItem(data, mlistWidget);
    mlistWidget->insertItem(1, lst1);
}

运行结果

  • 1.Server端
    这里写图片描述
  • 2.Client端
    这里写图片描述

    说明:这里只运行出来结果搜索结果只有一个,因为我只有一台机器运行了server,如果你条件允许,在多个机器上运行server,在用client搜索,结果就可以搜索到多个了,网络中的所有运行了server的ip都可以搜索到

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值