10

在我看来,较新的 Android 设备在 NAT 之后运行,其中本地地址是内部运营商或 LAN 地址,公共地址是路由器或运营商分配的外部地址。

然而,较新的手机使用网络接口返回的地址与访问 IP 检测服务时不同。

因此,通过直接 P2P SocketChannels 连接本身就失败了。

针对 Android 平台设计的此问题是否有任何常见的解决方法?谁能澄清是什么导致了这种类似 NAT 的安全问题?

任何指向 Java NAT 遍历教程示例不是论文或论文)的链接也将被视为有帮助(因为我不太确定如何在 Java 中实现它)。

我当然也会接受任何人提供的任何其他解决方案!

4

4 回答 4

6

Almost every phone or PC you will ever touch won't have a static public IP address, and therefore will require NAT traversal. It's not because of the device; the carrier or ISP put routers between your device and the public internet. Depending on your application, usually there are NAT-traversal libraries you can use, such as ice4j or STUNT.

于 2012-04-28T22:45:02.353 回答
3

我在自己的项目中这样做,发现这个问题并不复杂。

这是 node.js 中一个非常简单的 UDP 回显服务器

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 客户端只需向该节点服务器发送一条消息

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 Client UDP listener 通过 UDPholepunching 获取通用 msg 和你自己的 Global ip&port

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 发送方使用其他客户端的 IPremoteHost 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();
于 2014-01-30T23:59:15.683 回答
1

http://sourceforge.net/projects/jnat-pmplib/ 是java中NAT-PMP的一个实现。

于 2013-02-02T20:18:38.797 回答
0

我已经设法通过转发您在路由器连接期间使用的套接字来建立套接字。它对我有用。

更新

如果您使用的是 Windows (ipconfig),请通过 cmd.exe 查找您的 IP 地址;如果您使用的是 Linux (ifconfig),请通过终端会话查找您的 IP 地址。然后通过浏览器连接到它,应该有一个安全部分。转到端口转发并打开您在建立 ServerSocket 和 Socket 时使用的端口。使用 TCP 作为协议。请注意,这仅适用于您尝试从您的 wlan 外部进行连接的情况。

于 2012-04-28T22:20:42.237 回答