在項目中用的使用組播的方式接受udp數(shù)據(jù)罩润,順便就記錄一下相關(guān)姿勢开缎。
什么是組播(Multicast)
在發(fā)送方和每一個接受方之間實現(xiàn)點對多點的網(wǎng)絡(luò)傳輸田盈。組播是Ip網(wǎng)絡(luò)數(shù)據(jù)傳輸方式三種之一枪眉,其他兩種是廣播和單播访得。加入組播組之后可以接受到該組播中發(fā)送的消息荚斯,包括可以接受自己發(fā)出的組播。組播的IP地址范圍為224.0.0.0到239.255.255.255,有些同學(xué)接受不到組播有可能就是這個IP地址寫錯了拴清。
組播如何使用
組播在基本的udp傳輸實現(xiàn)上只要添加加入組播的api就可以了,比如之前項目udp使用 :
DatagramSocket socket = new DatagramSocket();
生成socket之后如果想發(fā)送udp包会通,使用:
DatagramPacket sendPacket
= new DatagramPacket(sendBuf ,sendBuf.length , addr , port);
其中sendBuf是要發(fā)送的字節(jié)數(shù)組口予,sendBuf.length是要發(fā)送內(nèi)容的長度,adds是服務(wù)器地址涕侈,port是服務(wù)器端口沪停。然后調(diào)用:
socket.send(sendPacket);
就將內(nèi)容發(fā)送出去了,當然相應(yīng)的網(wǎng)絡(luò)訪問權(quán)限得加上。接受數(shù)據(jù)這么使:
DatagramPacket recvPacket
= new DatagramPacket(recvBuf , recvBuf.length);
socket.receive(recvPacket);
其中recvBuf是接收需要的數(shù)組木张,recvBuf.length是接收內(nèi)容的長度众辨。如果接收內(nèi)容的長度小于udp一包的長度,那么接收到的內(nèi)容就是被閹割之后的舷礼。然后需要將接收和發(fā)送的代碼封裝一下鹃彻,實現(xiàn)在單獨的兩個線程中實現(xiàn)接收和發(fā)送。接收的話考慮到有可能同時有許多獨立的udp數(shù)據(jù)需要發(fā)送妻献,那么就使用同步隊列來保持這些要發(fā)送的udp包蛛株,然后從同步隊列中取出數(shù)據(jù)進行發(fā)送。
這時候要接收組播了育拨,又要兼容之前的代碼谨履,我是這么實現(xiàn)的:
DatagramSocket socket = new MulticastSocket();
((MuticastSocket) socket).joinGroup(InetAddress.getByName(GroupIP));
其中GroupIP為組播服務(wù)器的地址。這樣之后接收和發(fā)送的代碼均無需修改熬丧。
那么問題來了
那么問題真的來了笋粟,我手上有三款手機,只有一款手機可以正常接收組播析蝴。
然后查詢了一些資料害捕,查到得使用MulticastLock。
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
MulticastLock multicastLock = wifiManager
.createMulticastLock("multicast.test");
multicastLock.acquire();
還要添加相關(guān)權(quán)限
然并卵嫌变,加上之后接收不到組播的手機仍然接收不到吨艇。
同時又發(fā)現(xiàn),通過組播接收到的數(shù)據(jù)比通過點對點接收的要少腾啥,因為我們接收到數(shù)據(jù)之后會進行校驗东涡,組播接收的數(shù)據(jù)通過校驗的成功率要低的多,相同的代碼倘待,通過點對點的方式成功率要高的多還穩(wěn)定疮跑。初步估計是手機底層過濾掉了部分數(shù)據(jù)。
所以大神們凸舵,怎么解決這個問題祖娘。Who can help me?