Android: NAT Traversal?

允我心安 提交于 2019-11-27 15:14:10

问题


It appears to me that newer Android devices run behind a NAT, where the local address is an internal carrier or LAN address and the public address is the router or carrier assigned external address.

Nevertheless, newer phones don't return the same address using the NetworkInterface as when accessing an IP detection service.

Therefore, connecting via direct P2P SocketChannels inherently fails.

Are there any common workarounds to this problem designed for the Android platform? Can anyone clarify what is causing this NAT-like security issue?

Any links to Java NAT traversal tutorials or examples (NOT essays or theses) would also be appreciated as being helpful (as I'm not quite sure how to implement it in Java).

I will of course also accept any other solutions anyone has to offer!


回答1:


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.




回答2:


I do that in my own project and have found this issue is not that complicated.

Here's a very simple UDP echo server in node.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);

An android client simply send a msg to this node server

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 to obtain general msg and your own Global ip&port via 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();

Android Client UDP sender using other client's 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();



回答3:


Look at http://sourceforge.net/projects/jnat-pmplib/ It is an implementation of NAT-PMP in java.




回答4:


I've managed to establish sockets just by forwarding the sockets you're using during the connection in your router. It worked for me.

UPDATE

Find out your IP address through cmd.exe if your using Windows (ipconfig) or through a terminal session if your on Linux (ifconfig). Then connect to it through the browser and there should be a security section. Go to port forwarding and open up the ports your using when establishing you're ServerSocket and Socket. Use TCP as the protocol. Please note that this only applies if you're trying to connect from outside your wlan.



来源:https://stackoverflow.com/questions/10367727/android-nat-traversal

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!