Android:NAT Traversal?

时间:2012-04-28 21:34:39

标签: java android networking p2p nat

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

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

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

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

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

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

4 个答案:

答案 0 :(得分:6)

您将触摸的几乎所有手机或PC都没有静态公共IP地址,因此需要NAT遍历。这不是因为设备;运营商或ISP将路由器放在您的设备和公共互联网之间。根据您的应用程序,通常可以使用NAT遍历库,例如ice4jSTUNT

答案 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外部进行连接的情况。