一:思路
每一个设备需要联网就一定会有ip地址,如果连接wifi的话,那么ip地址会在此wifi下的子网之中。我们可以通过ping命令来判断ip是否被分配。ping通则代表此ip有设备。
安卓手机是基于Linux内核的,所以我们可以获取当前运行环境来进行ping命令。而设备可以通过wifimanager获取dhcpinfo来获取子网掩码以及本机ip。
子网掩码和ip地址可以获取得到主机号和广播地址。从广播地址开始ping完子网数目可以获取得到本局域网下的设备。
考虑到速度问题,可采用UDP方案进行实现
二:难点
1.首先,需要对ip地址和网关进行处理(获取之后发现给的是逆序的int值)
2.需要对多线程进行处理。开一个线程池来维护。(甚至可能会放入上千的子线程去ping)
三:实现
1.首先我们需要获取ping的环境
private Runtime mRuntime = Runtime.getRuntime();// 获取当前运行环境
private Process mProcess = null;// 进程
private String mCmdFrontPart = "ping -c 1 -w 3 ";
2.获取ip地址以及网关
这方面我们就需要通过安卓的WiFimanager获取DhcpInfo来获取(如果没有连接wifi的话是没有数据的哦)
3.对ip和网关进行处理
这里需要对ip和网关进行string的转化以及再转换为正序的数字类型进行加法处理。
return ((ip >> 24) & 0xFF) + "."+ ((ip >> 16) & 0xFF) + "."+((ip >> 8) & 0xFF) + "."+(ip & 0xFF);
return (Long.parseLong(ipArray[0]) << 24) +
(Long.parseLong(ipArray[1]) << 16) +
(Long.parseLong(ipArray[2])<< 8) +
Long.parseLong(ipArray[3]);
方面使用位运算还是可以处理的,代码也简洁明了。
udp方案:
DatagramPacket sendPack = new DatagramPacket(sendData, sendData.length, broadIP, DEVICE_FIND_PORT);
采用DatagramPacket向所有IP发送UDP信息,然后监听ARP文件
4.子网数目计算后对ip进行处理
我们可以知道,子网掩码与ip可以可以获取广播地址(如192.168.109.15/24),我们可以进行运算(与运算,&符号)
再一个,我们可以通过主机号获取到子网数目,子网掩码为一的就是网络号,为0的为主机号。通过主机号获取子网数目后创建线程放入线程中执行。
/**
* ip地址类型从Long转tring
* string格式192.168.109.15(正序)
* @param ip
* @return
*/
public static String IpFromlongToStrBySeq(long ip) {
return ((ip >> 24) & 0xFF) + "."+ ((ip >> 16) & 0xFF) + "."+((ip >> 8) & 0xFF) + "."+(ip & 0xFF);
}
/**
* ip地址从String转Long(正序)
* @param ip
* @return
*/
public static long IpStringTolongBySeq(String ip){
String[] ipArray = ip.split("\\.");
return (Long.parseLong(ipArray[0]) << 24) +
(Long.parseLong(ipArray[1]) << 16) +
(Long.parseLong(ipArray[2])<< 8) + Long.parseLong(ipArray[3]);
}
/**
* 根据子网掩码以及本机ip地址计算该子网的初始ip(逆序)
*/
public static long getBeginIp(int ip,long mask){
long beginIp = ip&mask;
return beginIp;
}
/**
* 计算子网数
*/
public static int getDevNumBySubNet(int len){
int maskLen = 32-len;
return 1<<maskLen;
}