3

2 台の PC (A と B としましょう) が各パブリック IP の NAT の背後にあるセットアップがあります。そのため、それぞれが独自の異なるプライベート IP を持っています。間にサーバーを使用しています。これにより、IPアドレスとポート番号が交換されます。また、内部ポート番号も交換します..!

ここに画像の説明を入力

というわけで、基本的にはこの設定です。

クライアント A と B は次のコードを実行します。

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Clientnew {

     public static void main(String[] args) throws Exception {
    // prepare Socket
    DatagramSocket clientSocket = new DatagramSocket();

    for(int i = 1;i<10;i++){
    // prepare Data
    byte[] sendData = "Hello".getBytes();
    // send Data to Serverc
    DatagramPacket sendPacket = new DatagramPacket(sendData,
            sendData.length, InetAddress.getByName("27.251.62.27"), 7070);
    clientSocket.send(sendPacket);

    //send localip and local port to server
         System.out.println("Sending Local info");
//   InetAddress IPAddressLocal = clientSocket.getLocalAddress();
   int PortLocal = clientSocket.getLocalPort();
        String msgInfoOfClient1 = PortLocal+":PortLocal";

        byte[] newData = msgInfoOfClient1.getBytes();
         System.out.println(msgInfoOfClient1);
        DatagramPacket sendLocalPacket = new DatagramPacket(newData, newData.length, InetAddress.getByName("27.251.62.27"), 7070);
        clientSocket.send(sendLocalPacket);

     // receive External Data ==> Format:"<External IP of other Client>-<External Port of other Client>"
    DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
    clientSocket.receive(receivePacket);

    // Convert Response to IP and Port
    String response = new String(receivePacket.getData());
    String[] splitResponse = response.split("-");
    InetAddress External_IP = InetAddress.getByName(splitResponse[0].substring(1));

    int External_Port = Integer.parseInt(splitResponse[1]);

    // output converted Data for check
    System.out.println("External IP: " + External_IP + " External PORT: " + External_Port);   


    // receive Internal Data ==> Format:"<Internal IP of other Client>-<Internal Port of other Client>"
    DatagramPacket anotherPacket = new DatagramPacket(new byte[1024], 1024);
    clientSocket.receive(anotherPacket);

    // Convert Response to IP and Port
    response = new String(anotherPacket.getData());
    splitResponse = response.split(":");
//    InetAddress Internal_IP = InetAddress.getByName(splitResponse[0].substring(1));

    int Internal_Port = Integer.parseInt(splitResponse[0]);

    // output converted Data for check
    System.out.println(" Internal PORT: " + Internal_Port);   
    }
     }
}

サーバーSのコードは次のとおりです。

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class Servernew {
    public static void main(String args[]) throws Exception {

        DatagramSocket serverSocket2 = new DatagramSocket(6588);
        // Waiting for Connection of Client1 on Port 7070
        // ////////////////////////////////////////////////

        // open serverSocket on Port 7070
        DatagramSocket serverSocket1 = new DatagramSocket(7070);

        for(int i= 1; i<10;i++){

        System.out.println("Waiting for Client 1 on Port "
            + serverSocket1.getLocalPort());

        // receive Data
        DatagramPacket receivePacket = new DatagramPacket(new byte[1024], 1024);
        serverSocket1.receive(receivePacket);

        // Get  IP-Address and Port of Client1
        InetAddress IPAddress1 = receivePacket.getAddress();
        int port1 = receivePacket.getPort();
        String FirstmsgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";

        System.out.println("Client1 External: " + FirstmsgInfoOfClient1);

        // Get Message from Client
        DatagramPacket anotherPacket = new DatagramPacket(new byte[1024], 1024);
        serverSocket1.receive(anotherPacket);

        // Decode the String
        String response = new String(anotherPacket.getData());
        String[] splitResponse = response.split(":");
//        InetAddress LocalIP1 = InetAddress.getByName(splitResponse[0].substring(1));
        int LocalPort1 = Integer.parseInt(splitResponse[0]);
//        int LocalPort1 = Integer.parseInt(splitResponse[1]);
//        String msgInfoOfClient1 = PortLocal+":PortLocal";
        String SecondmsgInfoOfClient1 = LocalPort1+":LocalPort1";

        System.out.println("Client1 Internal: " + SecondmsgInfoOfClient1);
//        System.out.println(response);



        // Waiting for Connection of Client2 on Port 6588
        // ////////////////////////////////////////////////

        // open serverSocket on Port 6588

//         DatagramSocket serverSocket2 = new DatagramSocket(6588);

        System.out.println("Waiting for Client 2 on Port "
            + serverSocket2.getLocalPort());

        // receive Data
        receivePacket = new DatagramPacket(new byte[1024], 1024);
        serverSocket2.receive(receivePacket);

        // GetIP-Address and Port of Client1
        InetAddress IPAddress2 = receivePacket.getAddress();
        int port2 = receivePacket.getPort();
        String FirstmsgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";

        System.out.println("Client2 External:" + FirstmsgInfoOfClient2);

         // Get Message from Client
        anotherPacket = new DatagramPacket(new byte[1024], 1024);
        serverSocket2.receive(anotherPacket);

        // Decode the String

        response = new String(anotherPacket.getData());
        splitResponse = response.split(":");
//        InetAddress LocalIP1 = InetAddress.getByName(splitResponse[0].substring(1));
        int LocalPort2 = Integer.parseInt(splitResponse[0]);
//        int LocalPort1 = Integer.parseInt(splitResponse[1]);
//        
        String SecondmsgInfoOfClient2 = LocalPort2+":LocalPort2";

        System.out.println("Client2 Internal: " + SecondmsgInfoOfClient2);

        // Send the Information to the other Client
        /////////////////////////////////////////////////

        // Send Information of Client2 to Client1
        serverSocket1.send(new DatagramPacket(FirstmsgInfoOfClient2.getBytes(),
            FirstmsgInfoOfClient2.getBytes().length, IPAddress1, port1));

        serverSocket1.send(new DatagramPacket(SecondmsgInfoOfClient2.getBytes(), 
                SecondmsgInfoOfClient2.getBytes().length, IPAddress1, port1));


        // Send Infos of Client1 to Client2
        serverSocket2.send(new DatagramPacket(FirstmsgInfoOfClient1.getBytes(),
            FirstmsgInfoOfClient1.getBytes().length, IPAddress2, port2));

        serverSocket2.send(new DatagramPacket(SecondmsgInfoOfClient1.getBytes(), 
                SecondmsgInfoOfClient1.getBytes().length, IPAddress2, port2));

            System.out.println("-----------------\n");
            System.out.println("---------------------");
        }

        //close Sockets
        serverSocket1.close();
        serverSocket2.close();
}
}

そして、出力は、内部ポートと外部ポート、およびパブリック IP を完全に交換していることです。

問題は、この情報を使用して A と B の間で TCP 接続を開くにはどうすればよいかということです。Java を使用して TCP パンチ ホールを実装するにはどうすればよいですか?

PS: TCP 接続であることが最も必要であり、そのために Java を使用する必要があります。

4

1 に答える 1

0

S で2 つ開きServerSocket、A と B のそれぞれからの接続を受け入れます (それぞれポート 62000 と 31000)。いずれの場合もインスタンスをaccept返す場合、 and を使用して、それぞれのandを相互に交差させます。それぞれにスレッドが必要です。SocketInputStreamOutputStreamPipedOutputStreamPipedInputStream

于 2015-07-21T10:57:57.547 に答える