2012-04-28 15 views
9

新しいAndroid搭載端末は、ローカルアドレスが内部通信事業者またはLANアドレスで、パブリックアドレスがルータまたはキャリア割り当ての外部アドレスであるNATの背後にあると思われます。Android:NATトラバーサル?

しかし、新しい電話機は、IP検出サービスにアクセスするときと同じようにNetworkInterfaceを使用して同じアドレスを返しません。

したがって、直接P2P SocketChannels経由の接続は本質的に失敗します。

この問題の一般的な回避策は、Androidプラットフォーム用に設計されていますか?このNATのようなセキュリティ上の問題の原因を明確にすることはできますか? (私はJavaでそれを実装する方法は非常にわからないよう)

JavaのNATトラバーサルへのリンクチュートリアルまたはませエッセイや論文)も有用であるとしていただければ幸いです。

もちろん、誰かが提供しなければならない他のソリューションも受け入れます!

+2

Androidデバイスには内部NATのようなものはありません。デバイスには1つまたは複数のネットワーク[interfaces](http://docs.oracle.com/javase/tutorial/networking/nifs/definition.html)があり、正しいものを聞いている場合は、外部から接続を取得できますあなたはインターネット許可を持っています)。アクセスしようとするネットワークパスとデバイスの間のネットワークパスを確認できない場合 – zapl

+0

NATはエンドデバイスとは関係ありません。デバイスにはIPアドレスが割り当てられています。それがルーティング可能であるかどうかは、アクセスポイント/ DHCPサーバーによって異なります。 –

+0

エンドデバイスと何か関係があります。モバイルネットワークインターフェースアドレスを使用して直接P2P接続をテストする場合、古いAndroidデバイス(Epic 4G)に接続しても正常に動作しますが、Galaxy S2に接続するときは正常に動作しません。 NetworkInterface.getNetWorkInterfacesメソッドによって返されたGalaxyのアドレスは、Epic 4Gの場合とは異なり、外部IPと一致しません。明らかに、電話のネットワーク設定で何かが変わった。 – bgroenks

答えて

0

私は、ルータの接続中に使用しているソケットを転送するだけで、ソケットを確立することができました。それは私のために働いた。

UPDATE

あなたのLinux(ifconfigコマンド)であれば、あなたのWindowsを使用している場合(IPCONFIG)cmd.exeのを通して、あなたのIPアドレスを見つけるか、ターミナルセッションを介して。ブラウザを使用して接続し、セキュリティセクションが必要です。あなたがServerSocketとSocketを確立するときに、ポート転送に行き、使用しているポートを開きます。プロトコルとしてTCPを使用します。 これは、wlanの外から接続しようとしている場合にのみ適用されます。

+0

例を具体的に説明できますか?これは面白い概念のようです。 – bgroenks

+0

@ ghostsoldier23私の更新を確認してください –

+3

ああ、ポートフォワーディング? NAT Traversalの全ポイントは、それを避けることです。 – bgroenks

6

あなたがタッチするほとんどの電話機やPCには、パブリックなパブリックIPアドレスがないため、NATトラバーサルが必要になります。デバイスのためではありません。キャリアまたはISPは、デバイスと公共のインターネットとの間にルータを設置します。アプリケーションによっては、普通はice4jSTUNTのようなNATトラバーサルライブラリがあります。

+0

ice4jとSTUNTの両方がUDPだけをサポートしていませんか? – bgroenks

4

私自身のプロジェクトでこれを行い、この問題はそれほど複雑ではないことがわかりました。

ここには、ノード内の非常に単純なUDPエコーサーバーがあります。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); 

アンドロイドクライアント単にこのノードサーバにMSGを送信

     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クライアントのUDPのリスナーUDPholepunching

を経由して、一般的なmsgと、独自のグローバルIP &ポートを取得するために
     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(); 

他のクライアントの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

目的は質問に返信することです –

関連する問題