2015-07-21 129 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

相关问题