Lo hago en mi propio proyecto y he descubierto que este problema no es tan complicado.
Aquí hay un servidor de eco UDP muy simple en el nodo.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);
Un cliente de Android sólo tiene que enviar un msg a este servidor de nodo
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 cliente UDP listner obtener msg general y su propio puerto IP global & través 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();
El cliente de Android UDP envía usando el IP de otro cliente 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();
No existe una NAT interna en los dispositivos Android. Un dispositivo tiene una o varias [interfaces] de red (http://docs.oracle.com/javase/tutorial/networking/nifs/definition.html) y si está escuchando en la correcta puede obtener conexiones desde el exterior (asumiendo tienes el permiso de internet). Si no puede verificar la ruta de red entre la que intenta acceder y su dispositivo. – zapl
NAT no tiene nada que ver con el dispositivo final. El dispositivo solo tiene asignada una dirección IP. Si eso es enrutable o no depende del punto de acceso/servidor DHCP. –
Debe tener algo que ver con el dispositivo final. Cuando se prueba una conexión P2P directa con la dirección de la interfaz de red móvil, funciona bien al conectarse a un dispositivo Android anterior (Epic 4G) pero no al conectarse al Galaxy S2. La dirección de Galaxy devuelta por el método NetworkInterface.getNetWorkInterfaces no coincide con la IP externa, mientras que la Epic 4G sí lo hace. Claramente, algo cambió con la configuración de red de los teléfonos. – bgroenks