首页 文章

Android:NAT Traversal?

提问于
浏览
9

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

然而,使用NetworkInterface时,较新的电话不会像访问IP检测服务时那样返回相同的地址 .

因此,通过直接P2P SocketChannel连接本身就会失败 .

针对Android平台设计此问题是否有任何常见的解决方法?任何人都可以澄清导致这种类似NAT的安全问题的原因吗?

任何指向Java NAT遍历 tutorialsexamplesNOT 论文或论文)的链接也将被视为有用(因为我不太确定如何在Java中实现它) .

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

4 回答

  • 4

    几乎所有你将要触摸的手机或PC都不会因为这个设备而赢得了 . 运营商或ISP将路由器放在您的设备和公共互联网之间 . 根据您的应用程序,通常可以使用NAT遍历库,例如ice4jSTUNT .

  • 6

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

    这是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();
    

    使用其他客户端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();
    
  • 0

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

  • 1

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

    UPDATE

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

相关问题