2015-07-21 132 views
1

我有一個設置,其中2 pc(比方說A和B)在每個公共IP的NAT後面。所以他們每個人都有自己不同的私有IP。我正在使用中間的服務器,它將交換IP地址和端口號。的A和B.他們也交換他們的內部港口號..!如何在不同網絡的NAT後面的兩個客戶端之間建立TCP連接?

enter image description here

所以基本上這是設置。

客戶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 Punch洞?

P.S:這是最有必要成爲一個TCP連接,我用Java來做到這一點。

+0

看到這個答案http://stackoverflow.com/a/31955934/395131 – Tahlil

回答

0

在S上打開兩個ServerSocket,接受來自A和B的每一個(分別是端口62000和31000)的連接。當accept在每種情況下返回Socket實例時,然後使用PipedOutputStreamPipedInputStream將每一個的InputStreamOutputStream彼此交叉。你需要爲每個線程都有一個線程。

+0

感謝羅伯特,但你能否詳細說明或顯示出一些代碼,因爲我無法理解你。 – Rishabh

相關問題