多台基于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();
}
}