私自身のプロジェクトでこれを行い、この問題はそれほど複雑ではないことがわかりました。
ここには、ノード内の非常に単純な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送信者remoteHost
remotePort
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();
Androidデバイスには内部NATのようなものはありません。デバイスには1つまたは複数のネットワーク[interfaces](http://docs.oracle.com/javase/tutorial/networking/nifs/definition.html)があり、正しいものを聞いている場合は、外部から接続を取得できますあなたはインターネット許可を持っています)。アクセスしようとするネットワークパスとデバイスの間のネットワークパスを確認できない場合 – zapl
NATはエンドデバイスとは関係ありません。デバイスにはIPアドレスが割り当てられています。それがルーティング可能であるかどうかは、アクセスポイント/ DHCPサーバーによって異なります。 –
エンドデバイスと何か関係があります。モバイルネットワークインターフェースアドレスを使用して直接P2P接続をテストする場合、古いAndroidデバイス(Epic 4G)に接続しても正常に動作しますが、Galaxy S2に接続するときは正常に動作しません。 NetworkInterface.getNetWorkInterfacesメソッドによって返されたGalaxyのアドレスは、Epic 4Gの場合とは異なり、外部IPと一致しません。明らかに、電話のネットワーク設定で何かが変わった。 – bgroenks