protocolo llmnr colombia java android udp ssdp

java - llmnr - protocolo mdns



No se pueden recibir paquetes UDP adecuados utilizando SSDP (3)

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

Mi aplicación envía algunos paquetes UDP que contienen un mensaje M-SEARCH relevante a la dirección de transmisión sin ningún problema. El problema es que debería obtener una respuesta adecuada de otros dispositivos que ejecutan un servidor UPNP. Por algún motivo, solo recibo exactamente 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 la transmisión de paquetes UDP está realmente hecha

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 cadenas de transmisión SSDP (Probablemente no relacionado con el problema que estoy experimentando, pero por las dudas)

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 incluye los permisos pertinentes:

<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 un emulador.

Cualquier ayuda sería apreciada.

Editar al comentar:

La multidifusión en sí debería funcionar sin problemas. Descargué 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 transmisión en 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í, sin duda es un problema de implementación. No hay nada malo con el dispositivo.


Extraño. Solucioné el problema pero realmente no estoy seguro de qué lo hizo funcionar.

Aquí hay 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 M-Search, incluido 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 hasta donde yo sé.


Seguí tu código y cambié algunas palabras a 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.


En la posible respuesta es que puede tener un dispositivo "antiguo". Al parecer, la multidifusión (de Java) se rompe antes de Android 2.3.7

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

Otra posibilidad es que es un problema específico del dispositivo; por ejemplo, de esta manera: https://.com/a/3714848/139985 . (No estoy diciendo que sea ese problema específico ...)

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

Parece que hay una variedad de causas diferentes para la multidifusión que no funciona en varios dispositivos Android ...