2012-04-28 4 views
9

로컬 주소가 내부 이동 통신사 또는 LAN 주소이고 공용 주소가 라우터 또는 이동 통신사가 할당 한 외부 주소 인 최신 안드로이드 장치가 NAT 뒤에 실행되는 것으로 보입니다.Android : NAT 순회?

그러나 최신 전화기는 IP 검색 서비스에 액세스 할 때처럼 NetworkInterface를 사용하여 동일한 주소를 반환하지 않습니다.

따라서 직접 P2P SocketChannel을 통한 연결이 실패합니다.

Android 플랫폼 용으로 설계된이 문제에 대한 일반적인 해결 방법이 있습니까? 누구나이 NAT와 비슷한 보안 문제의 원인을 명확히 할 수 있습니까?

자바 NAT 통과 튜토리얼 또는 (하지 에세이 또는 논문)에 대한 링크도 (내가 자바를 구현하는 방법을 아주 잘 모르겠어요으로) 도움이되는 것으로 평가 될 것입니다.

물론 다른 솔루션도 제공 할 예정입니다.

+2

Android 기기에는 내부 NAT와 같은 것이 없습니다. 장치에는 하나 이상의 네트워크 [인터페이스]가 있습니다 (http://docs.oracle.com/javase/tutorial/networking/nifs/definition.html). 올바른 장치에서 수신하는 경우 외부에서 연결을 얻을 수 있습니다 (가정 인터넷 사용 권한이 있음). 액세스를 시도하는 네트워크 경로와 장치 사이의 네트워크 경로를 확인할 수없는 경우 – zapl

+0

NAT는 최종 장치와 아무 관련이 없습니다. 장치에 IP 주소가 할당되었습니다. 라우팅 가능 여부는 액세스 포인트/DHCP 서버에 따라 다릅니다. –

+0

최종 장치와 관련이 있어야합니다. 모바일 네트워크 인터페이스 주소로 직접 P2P 연결을 테스트 할 때 이전 Android 기기 (Epic 4G)에 연결하면 제대로 작동하지만 Galaxy S2에 연결하면 제대로 작동하지 않습니다. Epic 4G가하는 반면 NetworkInterface.getNetWorkInterfaces 메서드가 반환 한 은하의 주소는 외부 IP와 일치하지 않습니다. 분명히 전화기의 네트워킹 설정이 변경되었습니다. – bgroenks

답변

0

저는 라우터에서 연결하는 동안 사용중인 소켓을 전달하기 만하면 소켓을 설정할 수있었습니다. 그것은 나를 위해 일했습니다.

UPDATE

경우가 리눅스 (ifconfig를)에서 Windows (ipconfig를) 또는 터미널 세션을 통해를 사용하는 경우 cmd.exe를 통해 IP 주소를 알아보십시오. 그런 다음 브라우저를 통해 연결하면 보안 섹션이 있어야합니다. 포트 포워딩으로 이동하여 서버 소켓과 소켓을 설정할 때 사용하는 포트를 엽니 다. TCP를 프로토콜로 사용하십시오. wlan 외부에서 연결하려는 경우에만 적용됩니다.

+0

예제를 작성하거나 제공 할 수 있습니까? 이것은 흥미로운 개념처럼 보입니다. – bgroenks

+0

@ ghostsoldier23 내 업데이트를 확인하십시오 –

+3

오, 포트 포워딩? NAT Traversal의 요점은 그것을 피하는 것입니다. – bgroenks

6

만지지 않을 모든 전화 또는 PC에는 고정 공용 IP 주소가 없으므로 NAT 통과가 필요합니다. 장치 때문이 아닙니다. 이동 통신사 또는 ISP는 장치와 공용 인터넷간에 라우터를 배치합니다. 응용 프로그램에 따라 보통 ice4j 또는 STUNT과 같이 사용할 수있는 NAT 통과 라이브러리가 있습니다.

+0

ice4j와 STUNT가 UDP 만 지원하지 않습니까? – bgroenks

4

나는 내 프로젝트에서 그렇게하며이 문제가 복잡하지 않다는 것을 알았습니다.

다음은 노드에있는 매우 간단한 UDP 에코 서버입니다.

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

JS 안드로이드 클라이언트는 단순히

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

UDPholepunching

를 통해 일반 MSG와 자신의 글로벌 IP & 포트를 얻기 위해

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

안드로이드 클라이언트 UDP의 청취자이 노드 서버에 MSG를 보내 다른 클라이언트의 IP를 사용하는 Android 클라이언트 UDP 발신자 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

대단한 답변입니다. 그것이 작동한다고 가정하십시오 (- : – wires

+0

게시 한 코드의 목적은 무엇입니까? –

+0

목적은 질문에 대답하는 것입니다. –