No se pueden recibir paquetes UDP adecuados mediante SSDP

Estoy tratando de implementar una funcionalidad SSDP muy simple en mi aplicación Android tomada desde aquí .

Mi aplicación envía algunos paquetes UDP que contienen un mensaje M-SEARCH relevante a la dirección de emisión sin ningún problema. El problema es que debería recibir una respuesta adecuada de otros dispositivos que estén ejecutando un servidor UPNP. Por alguna razón, sólo recibo los mismos paquetes que envié desde mi dispositivo Android.

MainActivity.java

@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); WifiManager wm = (WifiManager)getSystemService(Context.WIFI_SERVICE); WifiManager.MulticastLock multicastLock = wm.createMulticastLock("multicastLock"); multicastLock.setReferenceCounted(true); multicastLock.acquire(); setContentView(R.layout.activity_main); ((Button)this.findViewById(R.id.btnSendSSDPSearch)).setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btnSendSSDPSearch: new Thread(new Runnable() { @Override public void run() { SendMSearchMessage(); } }).start(); default: break; } } private void SendMSearchMessage() { SSDPSearchMsg searchContentDirectory = new SSDPSearchMsg(SSDPConstants.ST_ContentDirectory); SSDPSearchMsg searchAVTransport = new SSDPSearchMsg(SSDPConstants.ST_AVTransport); SSDPSearchMsg searchProduct = new SSDPSearchMsg(SSDPConstants.ST_Product); SSDPSocket sock; try { sock = new SSDPSocket(); for (int i = 0; i < 2; i++) { sock.send(searchContentDirectory.toString()); sock.send(searchAVTransport.toString()); sock.send(searchProduct.toString()); } while (true) { DatagramPacket dp = sock.receive(); //Here, I only receive the same packets I initially sent above String c = new String(dp.getData()); System.out.println(c); } } catch (IOException e) { // TODO Auto-generated catch block Log.e("M-SEARCH", e.getMessage()); } 

SSDPSocket.java donde se realiza la transmisión de paquetes UDP

 public class SSDPSocket { SocketAddress mSSDPMulticastGroup; MulticastSocket mSSDPSocket; InetAddress broadcastAddress; public SSDPSocket() throws IOException { mSSDPSocket = new MulticastSocket(55325); //Bind some random port for receiving datagram broadcastAddress = InetAddress.getByName(SSDPConstants.ADDRESS); mSSDPSocket.joinGroup(broadcastAddress); } /* Used to send SSDP packet */ public void send(String data) throws IOException { DatagramPacket dp = new DatagramPacket(data.getBytes(), data.length(), broadcastAddress,SSDPConstants.PORT); mSSDPSocket.send(dp); } /* Used to receive SSDP packet */ public DatagramPacket receive() throws IOException { byte[] buf = new byte[1024]; DatagramPacket dp = new DatagramPacket(buf, buf.length); mSSDPSocket.receive(dp); return dp; } public void close() { if (mSSDPSocket != null) { mSSDPSocket.close(); } } } 

SSDPSearchMsg.java para construir la cadena de difusión SSDP (Probablemente no relacionado con el problema que estoy experimentando, pero por si acaso)

 public class SSDPSearchMsg { static final String HOST = "Host:" + SSDP.ADDRESS + ":" + SSDP.PORT; static final String MAN = "Man:ssdp:discover"; static final String NEWLINE = System.getProperty("line.separator"); int mMX = 3; /* seconds to delay response */ String mST; /* Search target */ public SSDPSearchMsg(String ST) { mST = ST; } public int getmMX() { return mMX; } public void setmMX(int mMX) { this.mMX = mMX; } public String getmST() { return mST; } public void setmST(String mST) { this.mST = mST; } @Override public String toString() { StringBuilder content = new StringBuilder(); content.append(SSDP.SL_MSEARCH).append(NEWLINE); content.append(HOST).append(NEWLINE); content.append(MAN).append(NEWLINE); content.append(mST).append(NEWLINE); content.append("MX:" + mMX).append(NEWLINE); content.append(NEWLINE); return content.toString(); } } 

SSDPConstants.java

 public class SSDPConstants { /* New line definition */ public static final String NEWLINE = "\r\n"; public static final String ADDRESS = "239.255.255.250"; public static final int PORT = 1900; /* Definitions of start line */ public static final String SL_NOTIFY = "NOTIFY * HTTP/1.1"; public static final String SL_MSEARCH = "M-SEARCH * HTTP/1.1"; public static final String SL_OK = "HTTP/1.1 200 OK"; /* Definitions of search targets */ public static final String ST_RootDevice = "St: rootdevice"; public static final String ST_ContentDirectory = "St: urn:schemas-upnp-org:service:ContentDirectory:1"; public static final String ST_AVTransport = "St: urn:schemas-upnp-org:service:AVTransport:1"; public static final String ST_Product = "St: urn:av-openhome-org:service:Product:1"; /* Definitions of notification sub type */ public static final String NTS_ALIVE = "NTS:ssdp:alive"; public static final String NTS_BYE = "NTS:ssdp:byebye"; public static final String NTS_UPDATE = "NTS:ssdp:update"; } 

También me aseguré de que el manifiesto incluya permisos relevantes:

  <uses-permission android:name="android.permission.INTERNET"/> <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 

Estoy probando la aplicación en un dispositivo real, no en el emulador.

Cualquier ayuda sería apreciada.

Editar al comentar:

Multicast en sí debe funcionar sin problema. He descargado una aplicación llamada BubbleUPNP para probar la funcionalidad SSDP. Efectivamente, wireshark captura correctamente todos los mensajes enviados desde el teléfono a la dirección de difusión en el protocolo SSDP:

 M-SEARCH * HTTP/1.1 Man: "ssdp:discover" Mx: 3 Host: 239.255.255.250:1900 St: urn:schemas-upnp-org:service:AVTransport:1 

Y la respuesta

 HTTP/1.1 200 OK ST:urn:schemas-upnp-org:service:ContentDirectory:1 USN:uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232::urn:schemas-upnp-org:service:ContentDirectory:1 Location:http://10.175.95.4:2869/upnphost/udhisapi.dll?content=uuid:d5829e90-73ce-4213-9ad1-4e75dbdd0232 OPT:"http://schemas.upnp.org/upnp/1/0/"; ns=01 01-NLS:05f3dd08b4b4b5aafa1fe983fa447f49 Cache-Control:max-age=900 Server:Microsoft-Windows-NT/5.1 UPnP/1.0 UPnP-Device-Host/1.0 

Así que sí, esto es sin duda, un problema de implementación. Nada malo con el dispositivo.

Extraño. He solucionado el problema, pero estoy realmente no estoy seguro de lo que hizo que funcione.

He aquí algunos cambios que hice:

En lugar de asignar un puerto fijo, lo hice asignar dinámicamente un puerto disponible.

 public class SSDPSocket { SocketAddress mSSDPMulticastGroup; MulticastSocket mSSDPSocket; InetAddress broadcastAddress; public SSDPSocket() throws IOException { mSSDPSocket = new MulticastSocket(); broadcastAddress = InetAddress.getByName(SSDPConstants.ADDRESS); mSSDPSocket.joinGroup(broadcastAddress); } ... } 

También cambié la estructura del mensaje de M-Search, incluyendo su orden.

 public class SSDPSearchMsg { static final String HOST = "Host: " + SSDPConstants.ADDRESS + ":" + SSDPConstants.PORT; static final String MAN = "Man: \"ssdp:discover\""; static final String NEWLINE = "\r\n"; int mMX = 3; /* seconds to delay response */ String mST; /* Search target */ public SSDPSearchMsg(String ST) { mST = ST; } public int getmMX() { return mMX; } public void setmMX(int mMX) { this.mMX = mMX; } public String getmST() { return mST; } public void setmST(String mST) { this.mST = mST; } @Override public String toString() { StringBuilder content = new StringBuilder(); content.append(SSDPConstants.SL_MSEARCH).append(NEWLINE); content.append(MAN).append(NEWLINE); content.append("Mx: " + mMX).append(NEWLINE); content.append(HOST).append(NEWLINE); content.append(mST).append(NEWLINE); content.append(NEWLINE); return content.toString(); } } 

Y todo funciona de repente. Por qué funciona está más allá de mí. Mi implementación anterior sigue el protocolo SSDP en la medida de lo que puedo decir.

En la respuesta posible es que usted puede tener un dispositivo "viejo". Al parecer, la multidifusión (desde Java) está rota antes de Android 2.3.7

Referencia: https://stackoverflow.com/a/9836464/139985

Otra posibilidad es que se trata de un problema específico del dispositivo; Por ejemplo: https://stackoverflow.com/a/3714848/139985 . (No estoy diciendo que es ese problema específico …)

Otra es que la multidifusión está desactivada en las configuraciones del kernel: http://code.google.com/p/android/issues/detail?id=51195

Parece que hay una serie de causas diferentes para que la multidifusión no funcione en varios dispositivos Android …

Seguí tu código y cambiar algunas palabras en mayúsculas. Funciona.

 static final String HOST = "HOST: " + SSDPConstants.ADDRESS + ":" + SSDPConstants.PORT; static final String MAN = "MAN: \"ssdp:discover\""; 

No es necesario cambiar el orden en el mensaje MSEARCH.

  • Difusión de audio / vídeo desde android vía udp a wifi y escuchar con vlc
  • Comunicación UDP de Android
  • tengo dos aplicaciones android, se puede enviar la cadena a través de LAN en IP específico y otra aplicación para la recepción, pero quiero transmitir la cadena a través de LAN?
  • Cómo obtener TTL de un paquete UDP en Java?
  • Emulador de Android udp broadcast
  • No se puede establecer el valor DSCP en la aplicación android
  • No se pueden enviar paquetes UDP de la máquina de desarrollo a Android Emulator
  • Retraso / retraso enorme de UDP con Android
  • Paquetes UDP (vía WiFi Direct) nunca llegan
  • DatagramSocket.bind (); Socket excepción: no se puede asignar la dirección solicitada. Emulador de Android
  • Dirección de difusión de Android
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.