在我看来,较新的Android设备在NAT后运行,其中本地地址是内部运营商或LAN地址,公共地址是路由器或运营商分配的外部地址。
然而,较新的手机使用NetworkInterface时不会像访问IP检测服务时那样返回相同的地址。
因此,通过直接P2P SocketChannels连接本身就会失败。
针对Android平台设计此问题是否有任何常见的解决方法?任何人都可以澄清导致这种类似NAT的安全问题的原因吗?
任何指向Java NAT遍历教程或示例( NOT 论文或论文)的链接也会被视为有用(因为我'我不太确定如何在Java中实现它。
我当然也会接受任何人提供的任何其他解决方案!
答案 0 :(得分:6)
您将触摸的几乎所有手机或PC都没有静态公共IP地址,因此需要NAT遍历。这不是因为设备;运营商或ISP将路由器放在您的设备和公共互联网之间。根据您的应用程序,通常可以使用NAT遍历库,例如ice4j或STUNT。
答案 1 :(得分:4)
我在自己的项目中这样做,发现这个问题并不复杂。
这是node.js中非常简单的UDP echo服务器
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);
Android客户端只需将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获取通用消息和您自己的全局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();
Android客户端UDP发件人使用其他客户端的IP 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();
答案 2 :(得分:1)
看看http://sourceforge.net/projects/jnat-pmplib/ 它是java中NAT-PMP的一个实现。
答案 3 :(得分:0)
我设法通过转发您在路由器连接期间使用的套接字来建立套接字。它对我有用。
<强>更新强>
如果您使用Windows(ipconfig)或通过终端会话(如果您使用Linux(ifconfig)),请通过cmd.exe查找您的IP地址。然后通过浏览器连接到它,应该有一个安全部分。在建立ServerSocket和Socket时,转到端口转发并打开您使用的端口。使用TCP作为协议。 请注意,这仅适用于您尝试从您的wlan外部进行连接的情况。