Este código funciona perfectamente en Ubuntu, Windows y Mac OS X. También funciona bien con un Nexus One con Android 2.1.1.¿Se ha roto la multidifusión para Android 2.0.1 (actualmente en DROID) o me falta algo?
Empiezo a enviar y escuchar datagramas de multidifusión, y todas las computadoras y el Nexus One se verán perfectamente. Luego I ejecuta el mismo código en un Droid (Firmware 2.0.1), y todos obtendrán los paquetes enviados por el Droid, pero el droide solo escuchará sus propios paquetes.
Este es el método run()
de un hilo que escucha constantemente en un grupo de multidifusión para los paquetes entrantes enviados a ese grupo.
Estoy ejecutando mis pruebas en una red local donde tengo habilitada la compatibilidad de multidifusión en el enrutador. Mi objetivo es que los dispositivos se conozcan a medida que se conecten transmitiendo paquetes a un grupo de multidifusión.
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);
}
}
Este es el código que envía la multidifusión de Datagrama de cada interfaz de red válida disponible (que no es la interfaz de bucle).
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();
}
}
actualización (abril 2 ª 2010) he encontrado una manera de tener la interfaz de red del Droid de comunicarse mediante multidifusión: WifiManager.MulticastLock.
MulticastLock _wifiMulticastLock = ((WifiManager) context.getSystemService(Context.WIFI_SERVICE)).createMulticastLock("multicastLockNameHere");
_wifiMulticastLock.acquire();
Luego, cuando haya terminado ...
if (_wifiMulticastLock != null && _wifiMulticastLock.isHeld())
_wifiMulticastLock.release();
Después de hacer esto, el Droid comenzó a enviar y recibir datagramas UDP en un grupo de multidifusión.
actualización julio-6-2010
Por la petición, aquí está mi código actual, existe el siguiente método en una clase abstracta que puede ser utilizado tanto para receptores de difusión y multidifusión.
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();
}
}
Sus clases se extienden deben implementar onInit()
y onDatagramReceived()
Para un receptormultidifusión, onInit()
se ve algo como esto:
_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);
}
Estoy tratando de recibir paquetes de multidifusión en mi Nexus-One (firmware 2.1.1). Utilicé el código anterior, pero no tuve suerte hasta el momento. ¿Puedes adjuntar tu fuente completa para poder compararla con la mía?Gracias, Eyal – Eyal
Eya, he agregado una actualización, espero que ayude. – Gubatron