Questo codice funziona perfettamente in Ubuntu, Windows e Mac OS X. Funziona perfettamente anche con un Nexus One con Android 2.1.1.Multicast è rotto per Android 2.0.1 (attualmente sul DROID) o mi manca qualcosa?
Inizio a inviare e ad ascoltare i datagrammi multicast e tutti i computer e il Nexus One si vedranno perfettamente. Quindi I eseguo lo stesso codice su un Droid (Firmware 2.0.1), e tutti riceveranno i pacchetti inviati dal Droid, ma il droide ascolterà solo i propri pacchetti.
Questo è il metodo run()
di un thread che è costantemente in ascolto su un gruppo Multicast per i pacchetti in entrata inviati a quel gruppo.
Sto eseguendo i miei test su una rete locale in cui ho il supporto multicast abilitato nel router. Il mio obiettivo è far sì che i dispositivi si incontrino mentre arrivano online trasmettendo pacchetti a un gruppo multicast.
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);
}
}
Questo è il codice che invia il multicast Datagram da ogni interfaccia di rete valida a disposizione (che non è l'interfaccia di 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();
}
}
Update (2 aprile 2010) ho trovato un modo per avere l'interfaccia di rete del Droid di comunicare utilizzando Multicast: WifiManager.MulticastLock.
MulticastLock _wifiMulticastLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).createMulticastLock("multicastLockNameHere");
_wifiMulticastLock.acquire();
Poi, quando il gioco è fatto ...
if (_wifiMulticastLock != null && _wifiMulticastLock.isHeld())
_wifiMulticastLock.release();
Dopo che ho fatto questo, il Droid ha iniziato a inviare e ricevere datagrammi UDP su un gruppo multicast.
Aggiornamento luglio-6-2010
Per richiesta, ecco il mio codice attuale, il metodo successivo esiste una classe astratta che può essere utilizzato per entrambi i ricevitori Broadcast e 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();
}
}
Le classi che si estendono dovrebbero attuare onInit()
e onDatagramReceived()
Per un ricevitore Multicast, onInit()
sembra qualcosa di simile:
_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);
}
Sto provando a ricevere pacchetti multicast sul mio Nexus-One (firmware 2.1.1). Ho usato il codice sopra, ma finora non ho avuto fortuna. Puoi allegare la tua fonte completa in modo da poterla confrontare con la mia?Grazie, Eyal – Eyal
Eya, ho aggiunto un aggiornamento, spero che aiuti. – Gubatron