Socket廣播包經(jīng)常被用于局域網(wǎng)內(nèi)的兩臺(tái)設(shè)備之間互相發(fā)現(xiàn)和消息傳遞,在Android應(yīng)用開發(fā)過程中,也經(jīng)常會(huì)遇到這樣的需求,例如:兩臺(tái)Android設(shè)備之間、Android與手環(huán)等智能硬件之間、Android與Windows電腦之間等等。

創(chuàng)新互聯(lián)公司是專業(yè)的辰溪網(wǎng)站建設(shè)公司,辰溪接單;提供網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作,網(wǎng)頁設(shè)計(jì),網(wǎng)站設(shè)計(jì),建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行辰溪網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊(duì),希望更多企業(yè)前來合作!
本文主要介紹在Android中使用Socket開發(fā)廣播包程序時(shí)需要注意的編程事項(xiàng),以及解決方法。
首先給出一段Android發(fā)送廣播包的示例代碼:
DatagramSocket socket = new DatagramSocket(8000);
socket.setBroadcast(true);
InetAddress addr = InetAddress.getByName("255.255.255.255");
byte[] buffer = "Hello World".getBytes();
DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
packet.setAddress(addr);
packet.setPort(8086);
socket.send(packet);下面分析其中需要注意的地方:
1. 不要在主線程中發(fā)送廣播包
當(dāng)然,這個(gè)做Android開發(fā)的人應(yīng)該都知道,不能在UI線程中執(zhí)行任何網(wǎng)絡(luò)訪問相關(guān)的操作,由于廣播包的發(fā)送也屬于網(wǎng)絡(luò)操作,因此必須放到單獨(dú)的線程中執(zhí)行。
2. 廣播地址不建議使用“255.255.255.255”
上述代碼中,廣播包的目標(biāo)地址設(shè)置為了“255.255.255.255”,其實(shí),這并不是一種推薦的做法。
“255.255.255.255” 是一種受限的廣播地址,常用于在計(jì)算機(jī)不知道自己IP地址的時(shí)候發(fā)送,比如設(shè)備啟動(dòng)時(shí)向DHCP服務(wù)器索要地址等等,一般情況下,路由器不會(huì)轉(zhuǎn)發(fā)目標(biāo)為受限廣播地址的廣播包。
而且,有些路由器/Wi-Fi熱點(diǎn)不支持該廣播地址(例如:用Android手機(jī)做Wi-Fi熱點(diǎn)的時(shí)候),因此在程序中會(huì)出現(xiàn)“ENETUNREACH (Network is unreachable)”的異常,因此,為了保證程序成功發(fā)送廣播包,建議使用直接廣播地址,例如:當(dāng)前IP地址是 192.168.1.100,子網(wǎng)掩碼是 255.255.255.0 的情況下,廣播地址為:192.168.1.255,(具體的推算方法這里就不展開了,可以參考計(jì)算機(jī)網(wǎng)絡(luò)相關(guān)書籍)。
那么,如何得到本網(wǎng)段的直接廣播地址呢,下面是stackoverflow上面有位大牛分享的代碼:
public static InetAddress getBroadcastAddress(Context context) throws UnknownHostException {
WifiManager wifi = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
DhcpInfo dhcp = wifi.getDhcpInfo();
if(dhcp==null) {
return InetAddress.getByName("255.255.255.255");
}
int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask;
byte[] quads = new byte[4];
for (int k = 0; k < 4; k++)
quads[k] = (byte) ((broadcast >> k * 8) & 0xFF);
return InetAddress.getByAddress(quads);
}直接使用該函數(shù)即可得到正確的“廣播地址”,通過setAddress函數(shù)設(shè)置到DatagramPacket對象中即可。
3. Android設(shè)置為Wi-Fi熱點(diǎn)時(shí)的廣播地址
這是個(gè)比較大的坑,當(dāng)Android設(shè)備被設(shè)置為Wi-Fi熱點(diǎn)的時(shí)候,上面的函數(shù)得到的地址是"0.0.0.0",因此,我們需要探究當(dāng)Android設(shè)備被設(shè)置為Wi-Fi熱點(diǎn)的時(shí)候,它的IP地址究竟是多少?
有人研究了Android底層源碼發(fā)現(xiàn),當(dāng)Android設(shè)備被設(shè)置為Wi-Fi熱點(diǎn)的時(shí)候,其IP地址是hardcode寫死在源碼中的,地址是:“192.168.43.1”,對應(yīng)的廣播地址是:"192.168.43.255"
為此,我們需要寫個(gè)函數(shù)來判斷一下當(dāng)前Android手機(jī)是否處于Wi-Fi熱點(diǎn)模式下,如果是,則應(yīng)該使用上面給出的這個(gè)廣播地址,這里給出代碼示例:
protected static Boolean isWifiApEnabled(Context context) {
try {
WifiManager manager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE);
Method method = manager.getClass().getMethod("isWifiApEnabled");
return (Boolean)method.invoke(manager);
}
catch (NoSuchMethodException e) {
e.printStackTrace();
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return false;
}Android SDK并沒有開放判斷是否處于熱點(diǎn)模式的API,因此,我們需要通過反射的方式來得到,另外,注意添加權(quán)限:
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
4. 小結(jié)
本文涉及到的代碼被封裝到了一個(gè)Broadcaster.java的文件中,可以在博文最后的附件中下載,也可以從下面的地址下載:
https://github.com/Jhuster/Android/blob/master/Socket/Broadcaster.java
關(guān)于Android Socket發(fā)送廣播包的那些坑就總結(jié)到這里了,有任何疑問或者建議歡迎留言或者來信lujun.hust@gmail.com交流,或者關(guān)注我的新浪微博 @盧_俊 獲取最新的文章和資訊。
分享題目:AndroidSocket發(fā)送廣播包的那些坑
轉(zhuǎn)載來源:http://chinadenli.net/article22/ppsocc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)網(wǎng)站建設(shè)、手機(jī)網(wǎng)站建設(shè)、軟件開發(fā)、關(guān)鍵詞優(yōu)化、網(wǎng)頁設(shè)計(jì)公司、動(dòng)態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)