多台openwrt设备在局域网中搜索发现

该文介绍了一种通过在OpenWRT设备上建立UDP服务器监听广播请求,从而动态获取同一路由器下的物联网设备信息(如IP地址、设备数量和类型)的方法。程序示例包括OpenWRT上的UDP服务器端和Java编写的PC请求端。
摘要由CSDN通过智能技术生成

多台基于openwrt的物联网设备接入到同一台路由器下, 需要动态的获取这些设备的信息,

比如ip地址,设备数量,设备种类等等,可以在openwrt本地构建udp服务端来监听请求广播,然后回传给请求端信息即可.

openwrt udpserver本地程序

/**
udp广播监听端
create by iversondeng168
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <getopt.h>
#include <sys/un.h>
#include <math.h>
#include <memory.h>


#define  GET_DEVICE_INFO        "GETDEVICEINFO"

#define  SLEEP_TIME             (100*1000)
#define  BUF_SIZE               (128)

#define  I8                     char 
#define  UI8                    unsigned char
#define  UI16                   unsigned short



static I8* cmd_system(const I8* command)
{
     I8* result = "";
     FILE *fpRead;
     fpRead = popen(command, "r");
     I8 buf[1024];
     memset(buf,'\0',sizeof(buf));
     while(fgets(buf,1024-1,fpRead)!=NULL)
     {
          result = buf;
     }

     if(fpRead!=NULL)
          pclose(fpRead);

     return result;
}




//eg. udpserver 10000 &
int main(int argc,char* argv[])
{

    int  sock;
    int  ret;
    char buf[BUF_SIZE];

    struct sockaddr_in local;
    struct sockaddr_in client;
    socklen_t len                = sizeof(client);

    I8* tmp_ssid;
    I8  tmp_ssid_array[BUF_SIZE] = {0};
    I8* tmp_ip; 
    I8  tmp_ip_array[BUF_SIZE]   = {0};
    I8  name[BUF_SIZE]           = {0};
    int offset; 


	int tmp_len         = 0;
	int try_cnt         = 0;

    const int opt              = 1;
 
    if(argc != 2) return -1;



    //创建套接字
    sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        perror("socket error!");
        exit(1);
    }


    //将套接字与ip地址和端口号进行绑定
    local.sin_family            = AF_INET;
    local.sin_port              = htons(atoi(argv[1]));
    local.sin_addr.s_addr       = htonl(INADDR_ANY);

    
 
    //设置该套接字为广播类型,    
    ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt));  
    if(ret == -1)  
    {  
        printf("set socket error!");  
        exit(1);
    }  


    //绑定本地地址
    if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
    {
        perror("bind error!");
        exit(2);
    }
   

    while(1)
    { 
       //读取数据
       ret                       = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&client,&len);
       if(ret < 0)
       { 
           perror("recvfrom ret error!");
           exit(3);
       }
       else
       { 
		    //广播信息不匹配
            if(strcmp(GET_DEVICE_INFO,buf)) continue;

            buf[ret]             = 0;                       
            printf("[%s : %d]#  %s\n",inet_ntoa(client.sin_addr), ntohs(client.sin_port),buf);             


            //获取本机的wifi ssid
            tmp_ssid = cmd_system("uci get wireless.@wifi-iface[0].ssid");

            if(tmp_ssid == NULL) tmp_ssid = "";
            if(!strlen(tmp_ssid)) continue;

            memset(tmp_ssid_array,0,sizeof(tmp_ssid_array));
            memcpy(tmp_ssid_array,tmp_ssid,strlen(tmp_ssid));

            //获取本机的wlan0接口的ip地址
            tmp_ip   = cmd_system("ifconfig wlan0 | grep 'inet addr' | awk '{ print $2}' | awk -F: '{print $2}'");
            
            if(tmp_ip == NULL) tmp_ip = ""; 
            if(!strlen(tmp_ip)) continue;

            memset(tmp_ip_array,0,sizeof(tmp_ip_array));
            memcpy(tmp_ip_array,tmp_ip,strlen(tmp_ip));

            memset(name,0,sizeof(name));

          
		    //组合数据包
		    tmp_len = strlen(tmp_ip_array) - 1;
            memcpy(name,tmp_ip_array,tmp_len);
            offset = tmp_len;

            memcpy(name+offset,":",1);
            offset += 1;

            tmp_len = strlen(tmp_ssid_array) - 1;
            memcpy(name+offset,tmp_ssid_array,tmp_len);
            offset += tmp_len;

            name[offset] = 0;
            printf("name=%s\tlen=%d\n",name,strlen(name));

			try_cnt = 0;

LOOPS:
            //回传给广播请求者
            if(sendto(sock,name,strlen(name),0,(struct sockaddr*)&client,len) <= 0 &&
				try_cnt++ < 3)
            { 
                perror("sendto error!");
				usleep(SLEEP_TIME);

                goto LOOPS;
            }
       }
     
    }


    close(sock);

    return 0;
 }

PC请求端以java为例

/**
udp广播请求端
create by iversondeng168
*/
package com.app;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;


public class ipbroadcast {
	

	public static void main(String[] args) throws IOException, InterruptedException {

        //广播地址
        String host = "255.255.255.255";
		//广播的目的端口
        int port = 10000;
		//广播信息
        String message = "GETDEVICEINFO";


        byte[] recvdata;        
        InetAddress adds = InetAddress.getByName(host);
        DatagramSocket ds = new DatagramSocket();
            

        //循环搜索发现openwrt设备
        while(true)
        {
            DatagramPacket dp = new DatagramPacket(message.getBytes(),message.length(), adds, port);
            ds.send(dp);
            
            recvdata = new byte[128];             
            dp = new DatagramPacket(recvdata,recvdata.length);
            ds.receive(dp);
            
            System.out.println("recvdata="+new String(recvdata).toString());
            
            System.out.println("******************************************");
            
            Thread.sleep(3000);
         }
        
         //ds.close();
        }
		
}














利用jmdns发现局域网设备,在局域网内,你要通过一台主机和其他主机进行通信,你需要知道对方的ip地址,但是有些时候,你并不知道对方的ip地址,因为一般使用DHCP动态分配ip地址的局域网内,各个主机的IP地址是由DHCP服务器来帮你分配IP地址的。所以在很多情况下,你要知道对方的IP地址是比较麻烦的。 鉴于发现这篇文章最近的浏览量比较多,晚上也有不少转载,特别声明一下,文章水平可能不大够,只是我当时的一些理解,所以希望大家以批判的角度来看,然后又什么问题欢迎讨论。真心不希望误导大家^_^ mDNS就是来解决这个问题的。通过一个约定俗成的端口号,5353。(这个端口号应该是由IETF组织约定的。)每个进入局域网的主机,如果开启了mDNS服务的话,都会向局域网内的所有主机组播一个消息,我是谁,和我的IP地址是多少。然后其他也有该服务的主机就会响应,也会告诉你,它是谁,它的IP地址是多少。当然,具体实现要比这个复杂点。 比如,A主机进入局域网,开启了mDNS服务,并向mDNS服务注册一下信息:我提供FTP服务,我的IP是192.168.1.101,端口是21。当B主机进入局域网,并向B主机的mDNS服务请求,我要找局域网内FTP服务器,B主机的mDNS就会去局域网内向其他的mDNS询问,并且最终告诉你,有一个IP地址为192.168.1.101,端口号是21的主机,也就是A主机提供FTP服务,所以B主机就知道了A主机的IP地址和端口号了。 大概的原理就是这样子,mDNS提供的服务要远远多于这个,当然服务多但并不复杂。 在Apple 的设备上(电脑,笔记本,iphone,ipad等设备)都提供了这个服务。很多Linux设备也提供这个服务。Windows的设备可能没有提供,但是如果安装了iTunes之类的软件的话,也提供了这个服务。 这样就可以利用这个服务开发一些局域网内的自动发现,然后提供一些局域网内交互的应用了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值