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 を使用する必要があります。