2012-04-28 18 views
9

Wydaje mi się, że nowsze urządzenia z Androidem działają za NATem, gdzie adres lokalny jest wewnętrznym przewoźnikiem lub adresem sieci LAN, a publiczny adres jest adresem zewnętrznym routera lub operatora.Android: NAT Traversal?

Mimo to nowsze telefony nie zwracają tego samego adresu za pomocą interfejsu NetworkInterface, jak podczas uzyskiwania dostępu do usługi wykrywania IP.

W związku z tym łączenie się przez bezpośrednie kanały P2P SocketCannels z natury kończy się niepowodzeniem.

Czy są jakieś typowe obejścia tego problemu dla platformy Android? Czy ktoś może wyjaśnić, co powoduje ten problem bezpieczeństwa podobny do NAT?

Wszelkie linki do Java NAT tutoriale lub przykłady (NIE eseje czy tez) byłyby również ceniona jako pomocny (jak nie jestem pewien, jak wdrożyć je w Javie).

Oczywiście przyjmę również inne rozwiązania, które ktoś ma do zaoferowania!

+2

Na urządzeniach z Androidem nie ma wewnętrznych elementów typu NAT. Urządzenie ma jedną lub kilka sieci [interfejsów] (http://docs.oracle.com/javase/tutorial/networking/nifs/definition.html) i jeśli słuchasz tego, co właściwe, możesz uzyskać połączenia z zewnątrz (zakładając masz pozwolenie na Internet). Jeśli nie możesz sprawdzić ścieżki sieciowej między tą, która próbuje uzyskać dostęp do urządzenia. – zapl

+0

NAT nie ma nic wspólnego z urządzeniem końcowym. Urządzenie ma właśnie przypisany adres IP. To, czy jest to rutowanie, zależy od punktu dostępowego/serwera DHCP. –

+0

To musi mieć coś wspólnego z urządzeniem końcowym. Podczas testowania bezpośredniego połączenia P2P z adresem interfejsu sieci mobilnej działa dobrze łącząc się ze starszym urządzeniem z systemem Android (Epic 4G), ale nie podczas połączenia z Galaxy S2. Adres Galaxy zwracany przez metodę NetworkInterface.getNetWorkInterfaces nie pasuje do zewnętrznego adresu IP, podczas gdy Epic 4G to robi. Najwyraźniej coś się zmieniło w konfiguracji sieci telefonicznej. – bgroenks

Odpowiedz

0

Udało mi się założyć gniazda tylko przez przekierowanie gniazd, których używasz podczas połączenia w routerze. To zadziałało dla mnie.

UPDATE

Sprawdzaj swój adres IP poprzez cmd.exe jeśli używasz systemu Windows (ipconfig) lub poprzez sesji terminala jeśli na Linux (ifconfig). Następnie połącz się z nią za pomocą przeglądarki i powinna istnieć sekcja bezpieczeństwa. Przejdź do przekierowania portów i otwórz porty, z których korzystasz podczas ustanawiania konta ServerSocket i Socket. Użyj protokołu TCP jako protokołu. Należy pamiętać, że ma to zastosowanie tylko wtedy, gdy próbujesz nawiązać połączenie spoza sieci lokalnej.

+0

Czy możesz opracować lub podać przykład? To wydaje się interesującą koncepcją. – bgroenks

+0

@ ghostsoldier23 Sprawdź moją aktualizację –

+3

Och tylko przekazywanie portów? Cały punkt NAT Traversal polega na uniknięciu tego. – bgroenks

6

Prawie każdy telefon lub komputer, który kiedykolwiek dotkniesz, nie będzie miał statycznego publicznego adresu IP, a zatem będzie wymagał przejścia NAT. To nie z powodu urządzenia; operator lub dostawca internetu umieszcza routery między urządzeniem a publicznym Internetem. W zależności od aplikacji zwykle można korzystać z bibliotek translacji NAT, takich jak ice4j lub STUNT.

+0

Czy obsługa tylko technologii ice4j i STUNT nie obsługuje UDP? – bgroenks

4

Robię to w moim własnym projekcie i stwierdziłem, że ten problem nie jest aż tak skomplikowany.

Oto bardzo prosty serwer echa UDP w węźle.js

var dgram = require('dgram'); 

var socket = 
    dgram.createSocket('udp4'); 

socket 
    .on('listening', function() 
    { 
     var address = socket.address(); 
     console.log('socket listening ' + 
      address.address + ':' + address.port); 
    }) 
    .on('error', function(err) 
    { 
     console.log('socket error:\n' + err.stack); 
     socket.close(); 
    }) 
    .on('message', function(message, rinfo) 
    { 
     console.log('message: ' + message + ' from ' + 
      rinfo.address + ':' + rinfo.port); 

     var msg = new Buffer(rinfo.address + ':' + rinfo.port); 
     socket 
      .send(msg, 0, msg.length, 
       rinfo.port, rinfo.address, 
       function(err, bytes) 
       { 
        //socket.close(); 
       }); 

    }) 
    .bind(15000); 

android klient po prostu wysłać wiad z tym serwerem węzła

     System.out.println("UDP hole punching======================="); 

         class IOth extends Thread 
         { 
          @Override 
          public void run() 
          { 

           String sendMsg = "UDP hole punching"; 
           byte[] buf = sendMsg.getBytes(); 
           DatagramPacket packet; 

           System.out.println(HPremoteHost); // node server IP 
           System.out.println(HPremotePort); // 15000 
           try 
           { 
            packet = 
              new DatagramPacket(buf, buf.length, 
                InetAddress.getByName(HPremoteHost), HPremotePort); 

            ds.send(packet); 


           } 
           catch (Exception e) 
           { 
            System.out.println("error================"); 
            System.out.println(e); 
           } 
          } 
         } 

         IOth io00 = new IOth(); 
         io00.start(); 

Android Client UDP listner aby uzyskać ogólną wiad i własnego globalnego IP Port & poprzez UDPholepunching

     class IOLoop extends Thread 
         { 
          @Override 
          public void run() 
          { 
           try 
           { 
            String msg = "Native.UDPserver.open"; 

            SocketAddress sockAddress; 
            String address; 


            byte[] buf = new byte[1024]; 
            DatagramPacket packet = new DatagramPacket(buf, buf.length); 
            while (true) 
            { 
             try 
             { 
              ds.receive(packet); 
              sockAddress = packet.getSocketAddress(); 
              address = sockAddress.toString(); 

              msg = new String(buf, 0, packet.getLength()); 

              System.out.println(msg + " received !!! by " + address); 

              //this case is UDP HolePunching reaction 
              if (address.equals(HPaddress1)) 
              { 
               System.out.println(msg + "hole punched"); 

               //So you can obtain own Global ip& port here. 
               //exchange this information 
               //`remoteHost` `remotePort` to another client 
               //with some method (signaling server) 

              } 
             } 
             catch (IOException e) 
             { 
             } 
            } 

           } 
           catch (Exception e) 
           { 
           } 
          } 
         } 

         IOLoop io00 = new IOLoop(); 
         io00.start(); 

Klient systemu Android Klient UDP używa innego klienta IP remoteHostremotePort

     class IOth extends Thread 
         { 
          @Override 
          public void run() 
          { 

           String sendMsg = "This is a test message"; 
           byte[] buf = sendMsg.getBytes(); 
           DatagramPacket packet; 

           try 
           { 
            packet = 
              new DatagramPacket(buf, buf.length, 
                InetAddress.getByName(remoteHost), remotePort); 

            ds.send(packet); 

           } 
           catch (Exception e) 
           { 

           } 
          } 
         } 

         IOth io00 = new IOth(); 
         io00.start(); 
+0

świetna odpowiedź! zakładając, że działa (-: – wires

+0

Jaki jest cel opublikowanego przez Ciebie kodu? –

+0

Celem jest udzielenie odpowiedzi na pytanie –

Powiązane problemy