Router discovery by sending a broadcast packet using UPnP does not work

I am trying to implement a simple library that can detect a router through UPnP if the application is running in a NAT environment. I tried two methods: multi-leaf and datagram, to send a discovery packet to the router and try to listen on port 1901 for a response from the router. However, I have some problems with the codes. I tried the following three methods, and only the third one can get the answer from the router correctly. I have no idea why this does not work on the first and second paths.

First: send a packet with several sheets and listen on port 1901 for an answer.

Codes:

public void discovery () throws IOException { // SSDP port final int SSDP_PORT = 1900; final int SSDP_SEARCH_PORT = 1901; // Broadcast address for finding routers. final String SSDP_IP = "239.255.255.250"; // Time out of the connection. int TIMEOUT = 5000; // Localhost address. InetAddress localhost = InetAddress.getLocalHost(); // Send from localhost:1901 InetSocketAddress srcAddress = new InetSocketAddress(localhost, SSDP_SEARCH_PORT); // Send to 239.255.255.250:1900 InetSocketAddress dstAddress = new InetSocketAddress(InetAddress.getByName(SSDP_IP), SSDP_PORT); // ----------------------------------------- // // Construct the request packet. // // ----------------------------------------- // StringBuffer discoveryMessage = new StringBuffer(); discoveryMessage.append("M-SEARCH * HTTP/1.1\r\n"); discoveryMessage.append("HOST: " + SSDP_IP + ":" + SSDP_PORT + "\r\n"); discoveryMessage.append("ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1\r\n"); // ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n discoveryMessage.append("MAN: \"ssdp:discover\"\r\n"); discoveryMessage.append("MX: 2\r\n"); discoveryMessage.append("\r\n"); // System.out.println("Request: " + discoveryMessage.toString() + "\n"); byte[] discoveryMessageBytes = discoveryMessage.toString().getBytes(); DatagramPacket discoveryPacket = new DatagramPacket(discoveryMessageBytes, discoveryMessageBytes.length, dstAddress); // ----------------------------------- // // Send multi-cast packet. // // ----------------------------------- // MulticastSocket multicast = null; try { multicast = new MulticastSocket(null); multicast.bind(srcAddress); multicast.setTimeToLive(4); System.out.println("Send multicast request."); // ----- Sending multi-cast packet ----- // multicast.send(discoveryPacket); } finally { System.out.println("Multicast ends. Close connection."); multicast.disconnect(); multicast.close(); } // -------------------------------------------------- // // Listening to response from the router. // // -------------------------------------------------- // DatagramSocket wildSocket = null; DatagramPacket receivePacket = null; try { wildSocket = new DatagramSocket(SSDP_SEARCH_PORT); wildSocket.setSoTimeout(TIMEOUT); while (true) { try { System.out.println("Receive ssdp."); receivePacket = new DatagramPacket(new byte[1536], 1536); wildSocket.receive(receivePacket); String message = new String(receivePacket.getData()); System.out.println("Recieved messages:"); System.out.println(message); } catch (SocketTimeoutException e) { System.err.print("Time out."); break; } } } finally { if (wildSocket != null) { wildSocket.disconnect(); wildSocket.close(); } } } 

Result: the router executes the response packet (downsized by Wireshark, like the following screenshot), but the code does not receive anything. code 1 http://img705.imageshack.us/img705/6531/ssdp1.png

Code Result:

 Send multicast request. Multicast ends. Close connection. Receive ssdp. Time out. 

Second: send a datagram packet and listen on port 1901 for an answer.

Codes:

 public void discovery () throws IOException { // Ignore this part of the codes since they are the same as the first one. .............. // -------------------------------------------------- // // Listening to response from the router. // // -------------------------------------------------- // DatagramSocket wildSocket = null; DatagramPacket receivePacket = null; try { wildSocket = new DatagramSocket(SSDP_SEARCH_PORT); wildSocket.setSoTimeout(TIMEOUT); // ----- Sending datagram packet ----- // System.out.println("Send datagram packet."); wildSocket.send(discoveryPacket); while (true) { try { System.out.println("Receive ssdp."); receivePacket = new DatagramPacket(new byte[1536], 1536); wildSocket.receive(receivePacket); String message = new String(receivePacket.getData()); System.out.println("Recieved messages:"); System.out.println(message); } catch (SocketTimeoutException e) { System.err.print("Time out."); break; } } } finally { if (wildSocket != null) { wildSocket.disconnect(); wildSocket.close(); } } } 

Result: Wireshark does not receive anything. On ports 1900 and 1901, the packet is not disabled.

Code Result:

 Send datagram packet. Receive ssdp. Time out. 

Third: send packets with multiple sheets and datagrams and listen on port 1901 for an answer.

Codes:

 public void discovery () throws IOException { // Ignore this part of the codes since they are the same as the first one. .............. // ----------------------------------- // // Send multi-cast packet. // // ----------------------------------- // MulticastSocket multicast = null; try { multicast = new MulticastSocket(null); multicast.bind(srcAddress); multicast.setTimeToLive(4); System.out.println("Send multicast request."); // ----- Sending multi-cast packet ----- // multicast.send(discoveryPacket); } finally { System.out.println("Multicast ends. Close connection."); multicast.disconnect(); multicast.close(); } // -------------------------------------------------- // // Listening to response from the router. // // -------------------------------------------------- // DatagramSocket wildSocket = null; DatagramPacket receivePacket = null; try { wildSocket = new DatagramSocket(SSDP_SEARCH_PORT); wildSocket.setSoTimeout(TIMEOUT); // ----- Sending datagram packet ----- // System.out.println("Send datagram packet."); wildSocket.send(discoveryPacket); while (true) { try { System.out.println("Receive ssdp."); receivePacket = new DatagramPacket(new byte[1536], 1536); wildSocket.receive(receivePacket); String message = new String(receivePacket.getData()); System.out.println("Recieved messages:"); System.out.println(message); } catch (SocketTimeoutException e) { System.err.print("Time out."); break; } } } finally { if (wildSocket != null) { wildSocket.disconnect(); wildSocket.close(); } } } 

Result: send two broadcast packets and get two responses from the router. code 1 http://img707.imageshack.us/img707/1607/ssdp3.png

Code Result:

 Send multicast request. Multicast ends. Close connection. Send datagram packet. Receive ssdp. Recieved messages: HTTP/1.1 200 OK Cache-Control: max-age=300 Date: Wed, 06 Mar 2013 05:15:43 GMT Ext: Location: http://192.168.1.1:1780/InternetGatewayDevice.xml Server: POSIX UPnP/1.0 DD-WRT Linux/V24 ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1 USN: uuid:C42C1F3F-6E63-7FFC-F982-035B355D6E76::urn:schemas-upnp-org:device:InternetGatewayDevice:1 Receive ssdp. Recieved messages: HTTP/1.1 200 OK Cache-Control: max-age=300 Date: Wed, 06 Mar 2013 05:15:43 GMT Ext: Location: http://192.168.1.1:1780/InternetGatewayDevice.xml Server: POSIX UPnP/1.0 DD-WRT Linux/V24 ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1 USN: uuid:C42C1F3F-6E63-7FFC-F982-035B355D6E76::urn:schemas-upnp-org:device:InternetGatewayDevice:1 Receive ssdp. Time out. 

Is there any idea why the first and second methods could not request the router via UPnP? And why does the second one seem to be sending nothing?

Many thanks!

+7
source share
1 answer

I assume that this may be a problem with firmware at the OS + router level. Make sure your firewall is turned off.

First tag: This method does not work at all on my computer (OS X):

 Send multicast request. Exception in thread "main" java.io.IOException: Can't assign requested address Multicast ends. Close connection. at java.net.PlainDatagramSocketImpl.send(Native Method) at java.net.DatagramSocket.send(DatagramSocket.java:676) at Test.discovery(Test.java:55) at Test.main(Test.java:93) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:601) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 

However, after I changed:

  InetSocketAddress srcAddress = new InetSocketAddress(localhost, SSDP_SEARCH_PORT); 

to

  InetSocketAddress srcAddress = new InetSocketAddress(SSDP_SEARCH_PORT); 

It works great:

 Send multicast request. Multicast ends. Close connection. Receive ssdp. Recieved messages: HTTP/1.1 200 OK Cache-Control: max-age=60 Date: Sun, 04 Jan 1970 21:55:18 GMT Ext: Location: http://192.168.0.2:1780/InternetGatewayDevice.xml Server: POSIX UPnP/1.0 linux/5.20.61.0 ST: urn:schemas-upnp-org:device:InternetGatewayDevice:1 USN: uuid:C04E066F-F351-72B6-CCCF-E98237DCB05C::urn:schemas-upnp-org:device:InternetGatewayDevice:1 Receive ssdp. Time out. 

The second method: It works.

Third method: It works.

(too long for comments)

[edit]

If your goal is to create stable software, I would recommend that you stick with the usual way: https://stackoverflow.com/a/212418/

+1
source

All Articles