10

新しい Android デバイスは NAT の背後で実行されているように見えます。ローカル アドレスは内部キャリアまたは LAN アドレスであり、パブリック アドレスはルーターまたはキャリアによって割り当てられた外部アドレスです。

それにもかかわらず、新しい電話は、NetworkInterface を使用して、IP 検出サービスにアクセスするときと同じアドレスを返しません。

したがって、直接 P2P SocketChannel を介した接続は本質的に失敗します。

Android プラットフォーム用に設計されたこの問題に対する一般的な回避策はありますか? この NAT に似たセキュリティ問題の原因を明確にできる人はいますか?

Java NAT トラバーサルのチュートリアルまたは(エッセイや論文ではない) へのリンクも役に立ちます (Java での実装方法がよくわからないため)。

もちろん、誰かが提供しなければならない他のソリューションも受け入れます!

4

4 に答える 4

6

触れるほとんどすべての電話や PC には、静的なパブリック IP アドレスがないため、NAT トラバーサルが必要になります。デバイスが原因ではありません。通信事業者または ISP は、デバイスと公共のインターネットの間にルーターを配置します。アプリケーションによっては、通常、 ice4jSTUNTなど、使用できる NAT トラバーサル ライブラリがあります。

于 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();

UDPholepunching を介して一般的なメッセージと独自のグローバル IP とポートを取得するための Android クライアント UDP リスナー

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();
于 2014-01-30T23:59:15.683 に答える
1

http://sourceforge.net/projects/jnat-pmplib/を見てください 。Java での NAT-PMP の実装です。

于 2013-02-02T20:18:38.797 に答える
0

ルーターでの接続中に使用しているソケットを転送するだけで、なんとかソケットを確立できました。それは私のために働いた。

アップデート

Windows を使用している場合は cmd.exe を介して (ipconfig)、Linux を使用している場合はターミナル セッションを介して (ifconfig)、IP アドレスを調べます。次に、ブラウザを介して接続すると、セキュリティ セクションが表示されます。ポート転送に移動し、ServerSocket と Socket であることを確立するときに使用するポートを開きます。プロトコルとして TCP を使用します。これは、WLAN の外部から接続しようとしている場合にのみ適用されることに注意してください。

于 2012-04-28T22:20:42.237 に答える