2013-03-06 11 views
7

Próbuję zaimplementować prostą bibliotekę, która może wykryć router za pomocą protokołu UPnP, jeśli aplikacja działa w środowisku NAT. Próbowałem na dwa sposoby, multi-cast i datagram, do wysyłania pakietu odkrycia do routera i próbowałem wysłuchać portu 1901 dla odpowiedzi z routera. Jednak mam pewne problemy z kodami. Próbowałem następujących trzech sposobów, a tylko trzeci może poprawnie odbierać odpowiedź z routera. Nie mam pojęcia, dlaczego nie jest to praca na pierwszy i drugi sposób.Wykrywanie routera przez wysyłanie pakietu transmisji przy użyciu UPnP nie działa

Pierwsza: wyślij pakiet multi-cast i nasłuchuj portu 1901, aby uzyskać odpowiedź.

Kody:

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(); 
     } 
    } 
} 

Wynik: Router czy pakiet odpowiedzi (sniffered przez Wiresharka jako następnego ekranu), a kod nic nie odbierać. code 1 http://img705.imageshack.us/img705/6531/ssdp1.png

wynik Kod:

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

Drugi: pakiet wyślij datagram i nasłuchuje na porcie 1901 na odpowiedź.

Kody:

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(); 
     } 
    } 
} 

Wynik: Wireshark nie dostać nic. Nie pakiet jest sniffered na porcie 1900 i 1901.

wyniku kod:

Send datagram packet. 
Receive ssdp. 
Time out. 

Trzeci: wysłać grupowej i datagramu pakiety i nasłuchuje na porcie 1901 na odpowiedź.

Kody:

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(); 
     } 
    } 
} 

wynikowe: Wyślij dwóch pakietów broadcast sukces i dostać dwie odpowiedzi od routera. code 1 http://img707.imageshack.us/img707/1607/ssdp3.png

wynik Kod:

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. 

Czy istnieje jakiś pomysł dlaczego pierwszy i drugi sposób nie zwrócić się do routera za pośrednictwem protokołu UPnP? I dlaczego ten drugi nie wydaje niczego?

Wielkie dzięki!

+0

+ 1 dla miłej prezentacji pytania. – deadlock

Odpowiedz

1

Domyślam się, że może to być problem związany z oprogramowaniem układowym OS + routera. Upewnij się, że zapora jest wyłączona.

Pierwszy methot: Metoda ta nie działa w ogóle na moim komputerze (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) 

Jednak po tym, jak zmienić:

InetSocketAddress srcAddress = new InetSocketAddress(localhost, SSDP_SEARCH_PORT); 

do

InetSocketAddress srcAddress = new InetSocketAddress(SSDP_SEARCH_PORT); 

Działa to doskonale:

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. 

Druga metoda: Works.

Trzecia metoda: Działa.

(zbyt długi komentarz)

[edytuj]

W przypadku, gdy celem jest wytworzenie stabilnego oprogramowania, chciałbym polecić, aby trzymać się konwencjonalny sposób: https://stackoverflow.com/a/4405143

Powiązane problemy