在项目中用的使用组播的方式接受udp数据,顺便就记录一下相关姿势。
什么是组播(Multicast)
在发送方和每一个接受方之间实现点对多点的网络传输。组播是Ip网络数据传输方式三种之一,其他两种是广播和单播。加入组播组之后可以接受到该组播中发送的消息,包括可以接受自己发出的组播。组播的IP地址范围为224.0.0.0到239.255.255.255,有些同学接受不到组播有可能就是这个IP地址写错了。
组播如何使用
组播在基本的udp传输实现上只要添加加入组播的api就可以了,比如之前项目udp使用 :
DatagramSocket socket = new DatagramSocket();
生成socket之后如果想发送udp包,使用:
DatagramPacket sendPacket
= new DatagramPacket(sendBuf ,sendBuf.length , addr , port);
其中sendBuf是要发送的字节数组,sendBuf.length是要发送内容的长度,adds是服务器地址,port是服务器端口。然后调用:
socket.send(sendPacket);
就将内容发送出去了,当然相应的网络访问权限得加上。接受数据这么使:
DatagramPacket recvPacket
= new DatagramPacket(recvBuf , recvBuf.length);
socket.receive(recvPacket);
其中recvBuf是接收需要的数组,recvBuf.length是接收内容的长度。如果接收内容的长度小于udp一包的长度,那么接收到的内容就是被阉割之后的。然后需要将接收和发送的代码封装一下,实现在单独的两个线程中实现接收和发送。接收的话考虑到有可能同时有许多独立的udp数据需要发送,那么就使用同步队列来保持这些要发送的udp包,然后从同步队列中取出数据进行发送。
这时候要接收组播了,又要兼容之前的代码,我是这么实现的:
DatagramSocket socket = new MulticastSocket();
((MuticastSocket) socket).joinGroup(InetAddress.getByName(GroupIP));
其中GroupIP为组播服务器的地址。这样之后接收和发送的代码均无需修改。
那么问题来了
那么问题真的来了,我手上有三款手机,只有一款手机可以正常接收组播。
然后查询了一些资料,查到得使用MulticastLock。
WifiManager wifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
MulticastLock multicastLock = wifiManager
.createMulticastLock("multicast.test");
multicastLock.acquire();
还要添加相关权限
然并卵,加上之后接收不到组播的手机仍然接收不到。
同时又发现,通过组播接收到的数据比通过点对点接收的要少,因为我们接收到数据之后会进行校验,组播接收的数据通过校验的成功率要低的多,相同的代码,通过点对点的方式成功率要高的多还稳定。初步估计是手机底层过滤掉了部分数据。
所以大神们,怎么解决这个问题。Who can help me?
网友评论