2

NAT を介してクライアントに udp パケットを送信しようとしています。私たちは両方とも異なる NAT に属しています。STUN の理論に精通しているため、これを達成する方法は、経由で「ホールパンチ」することです。単純な STUN サーバー..

基本的に、サーバーは「接続されている」別のクライアントの外部IPアドレスとポートを返すだけで、それを使用してNAT経由でクライアントにパケットを送信できます...ただし、お互いの外部IPとポートを取得することはできました. .送信後もお互いから何も受信できません...フォーラムを検索し、何時間も頭を悩ませた後も、まだ解決策を思いつくことができません...STUNに精通している誰かができるかどうか疑問に思っていました.どこが間違っているかについての指針やアドバイスをください...

以下は、私たちが書いた小さなクライアントです...

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.SocketException;
import java.net.UnknownHostException;

import javax.swing.JOptionPane;


public class Client {

DatagramSocket socket;

public Client(){
    try {
        socket = new DatagramSocket();
        String data = "Initiate Stun Server";
        byte[] receive = data.getBytes();

        InetAddress host = InetAddress.getByName("the.stun.server.ipaddress");
        DatagramPacket pk = new DatagramPacket(receive,receive.length,host,9345);
        socket.send(pk); //send packet to server to initiate udp communication

        //spawn a new Thread to listen for any incoming packets
        new Thread(){
            public void run(){
                byte[] r;
                DatagramPacket rp;
                while(true){
                    System.out.println("Start listening on new socket");
                    r = new byte[1024];
                    rp = new DatagramPacket(r,r.length);
                    try {
                        socket.receive(rp);
                        System.out.println(new String(rp.getData()));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();

        String m = JOptionPane.showInputDialog(null,"Enter message to send");
        InetAddress connect = InetAddress.getByName(JOptionPane.showInputDialog(null,"Enter address to send message to"));//This is where we input the external ip
        int connectPort = Integer.parseInt(JOptionPane.showInputDialog(null,"Enter port of the addressee"));//input port
        DatagramPacket p = new DatagramPacket(m.getBytes(),m.getBytes().length,connect,connectPort);
        socket.send(p);

    } catch (SocketException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public static void main(String args[]){
    Client c = new Client();
}

}
4

1 に答える 1

2

実装したのは本当のSTUNプロトコルではありませんが、おそらく十分でしょう。:)

しかし、私はあなたのコードに2つの問題があると思います。

  1. ローカルポート番号を保存していません。スタンサーバーから応答を受け取ったら、socket.getLocalPortを呼び出して、「マップされたポート」に対応する内部ポート番号を確認する必要があります。マップされたポートは、スタンサーバーがあなたを見るポートです。NATは、同じローカルポートを使用する場合に限り、PCのIPからそのマップされたポートにアウトバウンドトラフィックをマップし続けます。したがって、ピアへの後続の接続では、(元のソケットを閉じた後)同じポートにデータグラムソケットを作成するか、ソケットがすでにバインドされているため、ピアへの後続の通信に同じソケットを再利用します。

  2. リモートホストの外部IPアドレスとローカルソケットのポートマッピングを知っているからといって、NATがパケットを転送しようとしているわけではありません。ほとんどのNATは、「IPおよびポート制限付き」として実行されます。これは、同じリモートホストのIPとポートに対応するアウトバウンドUDPパケットがあったことを認識している場合にのみ、NATを介したインバウンドトラフィック(UDPパケットを含む)を許可することを意味します。このルールが設定されていないと、NATの背後にあるどのPCにパケットを転送するかがわかりません。一般的なNATトラバーサル手法は、両方のピアが単純な1バイトのデータグラムを同時に相互に送信し、繰り返し(複数回)試行することです。最初のパケットは、ホストを離れて自身のNATから抜け出そうとしますが、リモートNATによってブロックされる可能性があります(ユーザーが誰であるかがわからないため)。ただし、NATは、相手側が正常に送信するためのマッピングおよび転送エントリを作成します。最終的に、両方のNATは、両方のピア間のトラフィックを許可および転送します。

ポートマッピングの動作が予測できないタイプのNATもあります。(ポートマッピングはIPごとに変更されます)。これらは(STUNを使用して)トラバースするのは困難ですが、反対側に正常に動作するNATがある場合は、通常は問題なく機能します。幸い、これらのタイプのNATは以前よりもまれです。

ここにいくつかのリンクがあります:

ICE(STUNおよびTURNの使用によるP2Pの標準メカニズム):http://en.wikipedia.org/wiki/Interactive_Connectivity_Establishment

しばらく前に私が与えた一言で言えば答えの私のP2P接続。

また、私のSTUNサーバーコードベースを使用するための露骨なプラグ。JStunクライアントライブラリと組み合わせて使用​​できます。

于 2012-06-08T07:47:58.560 に答える