2017-07-06 13 views
0

以下に2つのGroovyサブプログラムがあり、以下にプレーンUDPソケットを介してメッセージを送信します。彼らは127.0.0.1に送信されたときにメッセージを正常に受信します。しかし、パブリックIPアドレスに送信するときにはメッセージは受信されません(マシンはNATの背後にあります)。パブリックIPアドレスでUDPホールパンチが機能しないのはなぜですか?

なぜ穴が穿孔されないのですか?それを修正する方法は?

私は以前にJavaライブラリを介して公開STUNサーバーに問い合わせを試みましたが、同じ公開IPアドレスで応答していましたので、ここでwtfismyip.comを使用しています。

class GroovyTest { 

static String PUBLIC_IP = new URL('https://wtfismyip.com/text').text.trim() 
//static String PUBLIC_IP = '127.0.0.1' // works fine 

static void main(String[] args) { 
    runInstance(11111, 22222) 
    runInstance(22222, 11111) 
} 

static void runInstance(int thisPort, int anotherPort) { 
    def socket = new DatagramSocket(thisPort) 
    Thread.start { 
     // message listener 
     byte[] buf = new byte[1024] 
     while (true) { 
      DatagramPacket packet = new DatagramPacket(buf, buf.length); 
      socket.receive(packet); 
      InetAddress remoteAddr = packet.getAddress(); 
      int remotePort = packet.getPort(); 
      String sentence = new String(packet.getData(), 0, packet.length); 
      println("server-$thisPort: received [$sentence] from ${remoteAddr.hostAddress}:${remotePort}") 
     } 
    } 
    Thread.start { 
     // message sender 
     while (true) { 
      println("client-$thisPort: sending to ${PUBLIC_IP}:${anotherPort}...") 
      byte[] buf = ("Hello " + System.currentTimeMillis()).bytes 
      DatagramPacket packet = new DatagramPacket(buf, buf.length, InetAddress.getByName(PUBLIC_IP), anotherPort) 
      socket.send(packet) 
      Thread.sleep(2000) 
     } 
    } 
} 

} 
+2

'新しいURL( 'https://wtfismyip.com/text').text.trim()' - 本当ですか? –

+0

@shmosel Oh Groovy –

+1

https://stackoverflow.com/a/8524609/104458 – selbie

答えて

0

あなたの問題はwtfismyipによって返されたIPアドレスがコンピュータに割り当てられていないネットワーク上のルーターのIPアドレスであるという事実に由来します。ルータのパブリックIPにデータグラムを送信しようとすると、おそらくルータからICMP Destination Unreachableエラーメッセージが表示されます。この動作が必要な場合、ルーターには、ローカルのIPアドレスにインバウンドUDPトラフィックを転送できるポート転送機能がいくつかあります。

0
私は成功し、単に私が応答していUDPパケットからアドレスとポートの詳細を取ることによって、NATルータの背後UDPパケットに返信されてきた

...

DatagramSocket socket = new DatagramSocket(port); 
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length); 
socket.receive(receivePacket); 

DatagramPacket sendPacket = new DatagramPacket(sendBuffer, sendBuffer.length, 
    receivePacket.getAddress(), receivePacket.getPort()); 
socket.send(sendPacket); 

コードは、その中に、より堅牢ですパケットがどこから来たのか、途中で発生したアドレス変換は問題ではありません。常に正しい場所に返信します。

2つの異なるポート番号を使用しています。 "thisPort"と "anotherPort"。私が知る限り、穴あけは、同じポート番号で返信する場合にのみ機能します。これはセキュリティ上の理由から理にかなっています。

私のアバターに描かれている私の頭の上にある海洋ロボットは、このUDPホールパンチング技術を使用しています。

関連する問題