Mã này hoạt động hoàn hảo trên Ubuntu, Windows và Mac OS X. Nó cũng hoạt động tốt với Nexus One chạy Android 2.1.1.Multicast có bị hỏng cho Android 2.0.1 (hiện tại trên DROID) hay tôi đang thiếu thứ gì đó?
Tôi bắt đầu gửi và nghe các gói dữ liệu đa hướng và tất cả các máy tính và Nexus One sẽ nhìn thấy nhau một cách hoàn hảo. Sau đó, tôi chạy cùng một mã trên Droid (Firmware 2.0.1) và mọi người sẽ nhận được các gói được gửi bởi Droid, nhưng droid sẽ chỉ nghe các gói riêng của mình.
Đây là phương pháp run()
của chuỗi liên tục lắng nghe trên nhóm Multicast cho các gói gửi đến được gửi đến nhóm đó.
Tôi đang chạy các thử nghiệm của mình trên mạng cục bộ nơi tôi đã bật hỗ trợ đa phương tiện trong bộ định tuyến. Mục tiêu của tôi là để các thiết bị gặp nhau khi chúng trực tuyến bằng cách phát các gói cho một nhóm phát đa hướng.
public void run() {
byte[] buffer = new byte[65535];
DatagramPacket dp = new DatagramPacket(buffer, buffer.length);
try {
MulticastSocket ms = new MulticastSocket(_port);
ms.setNetworkInterface(_ni); //non loopback network interface passed
ms.joinGroup(_ia); //the multicast address, currently 224.0.1.16
Log.v(TAG,"Joined Group " + _ia);
while (true) {
ms.receive(dp);
String s = new String(dp.getData(),0,dp.getLength());
Log.v(TAG,"Received Package on "+ _ni.getName() +": " + s);
Message m = new Message();
Bundle b = new Bundle();
b.putString("event", "Listener ("+_ni.getName()+"): \"" + s + "\"");
m.setData(b);
dispatchMessage(m); //send to ui thread
}
} catch (SocketException se) {
System.err.println(se);
} catch (IOException ie) {
System.err.println(ie);
}
}
Đây là mã gửi Multicast Datagram ra khỏi mọi giao diện mạng hợp lệ có sẵn (không phải giao diện loopback).
public void sendPing() {
MulticastSocket ms = null;
try {
ms = new MulticastSocket(_port);
ms.setTimeToLive(TTL_GLOBAL);
List<NetworkInterface> interfaces = getMulticastNonLoopbackNetworkInterfaces();
for (NetworkInterface iface : interfaces) {
//skip loopback
if (iface.getName().equals("lo"))
continue;
ms.setNetworkInterface(iface);
_buffer = ("FW-"+ _name +" PING ("+iface.getName()+":"+iface.getInetAddresses().nextElement()+")").getBytes();
DatagramPacket dp = new DatagramPacket(_buffer, _buffer.length,_ia,_port);
ms.send(dp);
Log.v(TAG,"Announcer: Sent packet - " + new String(_buffer) + " from " + iface.getDisplayName());
}
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e2) {
e2.printStackTrace();
}
}
Cập nhật (ngày 2 tháng 4 2010) Tôi tìm thấy một cách để có giao diện mạng của Droid để giao tiếp sử dụng Multicast: WifiManager.MulticastLock.
MulticastLock _wifiMulticastLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).createMulticastLock("multicastLockNameHere");
_wifiMulticastLock.acquire();
Sau đó, khi bạn đã hoàn tất ...
if (_wifiMulticastLock != null && _wifiMulticastLock.isHeld())
_wifiMulticastLock.release();
Sau khi tôi đã làm điều này, Droid bắt đầu gửi và nhận UDP datagrams vào một nhóm Multicast.
Cập nhật tháng bảy-6-2010
Theo yêu cầu, đây là mã hiện tại của tôi, phương pháp tiếp theo tồn tại trên một lớp trừu tượng có thể được sử dụng cho cả máy thu phát sóng và Multicast.
public void run() {
onInit();
try {
byte[] data = new byte[65535];
while (isProcessing()) {
try {
DatagramPacket receivedDatagram = new DatagramPacket(data, data.length);
_socket.receive(receivedDatagram);
onDatagramReceived(receivedDatagram);
data = new byte[65535]; // This pattern is for saving memory allocation.
} catch (InterruptedIOException e) {
if (!isProcessing())
break;
}
} // while
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
} finally {
onStop();
_socket.close();
_socket.disconnect();
}
}
lớp mở rộng của bạn nên thực hiện onInit()
và onDatagramReceived()
Đối với một Multicast nhận, onInit()
trông giống như thế này:
_socket = new MulticastSocket(PORT_MULTICAST);
InetAddress groupAddress = InetAddress.getByAddress(MULTICAST_GROUP_ADDRESS);
InetAddress groupInetAddress = FrostWireUtils.fastResolveAddress(groupAddress); //reflection hack to not resolve ips
try {
_socket.setSoTimeout(500);
_socket.setTimeToLive(MULTICAST_TTL_GLOBAL);
_socket.setReuseAddress(true);
_socket.setNetworkInterface(
WifiUtils.getWifiNetworkInterface());
_socket.joinGroup(groupInetAddress);
WifiUtils.lockMulticast();
} catch (Exception e) {
Log.e(TAG, e.getMessage(), e);
}
Tôi đang cố gắng nhận các gói Multicast trên Nexus-One (firmware 2.1.1). Tôi đã sử dụng mã ở trên, nhưng không có may mắn cho đến nay. Bạn có thể đính kèm nguồn hoàn chỉnh của mình để tôi có thể so sánh nó với tôi không?Cảm ơn, Eyal – Eyal
Eya, tôi đã thêm bản cập nhật, hy vọng nó sẽ giúp ích. – Gubatron