一:思路
每一個設(shè)備需要聯(lián)網(wǎng)就一定會有ip地址,如果連接wifi的話,那么ip地址會在此wifi下的子網(wǎng)之中。我們可以通過ping命令來判斷ip是否被分配。ping通則代表此ip有設(shè)備。
安卓手機是基于Linux內(nèi)核的,所以我們可以獲取當(dāng)前運行環(huán)境來進行ping命令。而設(shè)備可以通過wifimanager獲取dhcpinfo來獲取子網(wǎng)掩碼以及本機ip。
子網(wǎng)掩碼和ip地址可以獲取得到主機號和廣播地址。從廣播地址開始ping完子網(wǎng)數(shù)目可以獲取得到本局域網(wǎng)下的設(shè)備。
考慮到速度問題,可采用UDP方案進行實現(xiàn)
二:難點
1.首先,需要對ip地址和網(wǎng)關(guān)進行處理(獲取之后發(fā)現(xiàn)給的是逆序的int值)
2.需要對多線程進行處理。開一個線程池來維護。(甚至可能會放入上千的子線程去ping)
三:實現(xiàn)
1.首先我們需要獲取ping的環(huán)境
private Runtime mRuntime = Runtime.getRuntime();// 獲取當(dāng)前運行環(huán)境
private Process mProcess = null;// 進程
private String mCmdFrontPart = "ping -c 1 -w 3 ";
2.獲取ip地址以及網(wǎng)關(guān)
這方面我們就需要通過安卓的WiFimanager獲取DhcpInfo來獲?。ㄈ绻麤]有連接wifi的話是沒有數(shù)據(jù)的哦)
3.對ip和網(wǎng)關(guān)進行處理
這里需要對ip和網(wǎng)關(guān)進行string的轉(zhuǎn)化以及再轉(zhuǎn)換為正序的數(shù)字類型進行加法處理。
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發(fā)送UDP信息,然后監(jiān)聽ARP文件
4.子網(wǎng)數(shù)目計算后對ip進行處理
我們可以知道,子網(wǎng)掩碼與ip可以可以獲取廣播地址(如192.168.109.15/24),我們可以進行運算(與運算,&符號)
再一個,我們可以通過主機號獲取到子網(wǎng)數(shù)目,子網(wǎng)掩碼為一的就是網(wǎng)絡(luò)號,為0的為主機號。通過主機號獲取子網(wǎng)數(shù)目后創(chuàng)建線程放入線程中執(zhí)行。
/**
* ip地址類型從Long轉(zhuǎn)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轉(zhuǎn)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]);
}
/**
* 根據(jù)子網(wǎng)掩碼以及本機ip地址計算該子網(wǎng)的初始ip(逆序)
*/
public static long getBeginIp(int ip,long mask){
long beginIp = ip&mask;
return beginIp;
}
/**
* 計算子網(wǎng)數(shù)
*/
public static int getDevNumBySubNet(int len){
int maskLen = 32-len;
return 1<<maskLen;
}