title: UDP Hole Punching Java Example
body: <p>I want to do UDP Hole Punching with two clients with the help of a server with a static IP. The server waits for the two clients on port 7070 and 7071. After that it sends the IP address and port to each other. This part is working fine. But I'm not able to establish a communication between the two clients. I tried the code in different Wifi networks and in 3G mobile network. The client program throws the IO-Exception "No route to host". 
  The client code is used for both clients. Once executed with port 7070 and once with 7071.</p>
  
  <p>Do you think I've implemented the UDP hole punching concept correctly? Any ideas to make it work? 
  Here's the server code first, followed by the client code.</p>
  
  <p>Thank you for help.</p>
  
  <p><strong>Code of server:</strong></p>
  
  <pre><code>public class UDPHolePunchingServer {
  
      public static void main(String args[]) throws Exception {
  
      // Waiting for Connection of Client1 on Port 7070
      // ////////////////////////////////////////////////
  
      // open serverSocket on Port 7070
      DatagramSocket serverSocket1 = new DatagramSocket(7070);
  
      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 msgInfoOfClient1 = IPAddress1 + "-" + port1 + "-";
  
      System.out.println("Client1: " + msgInfoOfClient1);
  
      // Waiting for Connection of Client2 on Port 7071
      // ////////////////////////////////////////////////
  
      // open serverSocket on Port 7071
      DatagramSocket serverSocket2 = new DatagramSocket(7071);
  
      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 msgInfoOfClient2 = IPAddress2 + "-" + port2 + "-";
  
      System.out.println("Client2:" + msgInfoOfClient2);
  
      // Send the Information to the other Client
      // /////////////////////////////////////////////////
  
      // Send Information of Client2 to Client1
      serverSocket1.send(new DatagramPacket(msgInfoOfClient2.getBytes(),
              msgInfoOfClient2.getBytes().length, IPAddress1, port1));
  
      // Send Infos of Client1 to Client2
      serverSocket2.send(new DatagramPacket(msgInfoOfClient1.getBytes(),
              msgInfoOfClient1.getBytes().length, IPAddress2, port2));
  
      //close Sockets
      serverSocket1.close();
      serverSocket2.close();
  }
  </code></pre>
  
  <p><strong>Code of client</strong></p>
  
  <pre><code>public class UDPHolePunchingClient {
  
      public static void main(String[] args) throws Exception {
      // prepare Socket
      DatagramSocket clientSocket = new DatagramSocket();
  
      // prepare Data
      byte[] sendData = "Hello".getBytes();
  
      // send Data to Server with fix IP (X.X.X.X)
      // Client1 uses port 7070, Client2 uses port 7071
      DatagramPacket sendPacket = new DatagramPacket(sendData,
              sendData.length, InetAddress.getByName("X.X.X.X"), 7070);
      clientSocket.send(sendPacket);
  
      // receive Data ==&gt; Format:"&lt;IP of other Client&gt;-&lt;Port of other Client&gt;"
      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 ip = InetAddress.getByName(splitResponse[0].substring(1));
  
      int port = Integer.parseInt(splitResponse[1]);
  
      // output converted Data for check
      System.out.println("IP: " + ip + " PORT: " + port);
  
      // close socket and open new socket with SAME localport
      int localPort = clientSocket.getLocalPort();
      clientSocket.close();
      clientSocket = new DatagramSocket(localPort);
  
      // set Timeout for receiving Data
      clientSocket.setSoTimeout(1000);
  
      // send 5000 Messages for testing
      for (int i = 0; i &lt; 5000; i++) {
  
          // send Message to other client
          sendData = ("Datapacket(" + i + ")").getBytes();
          sendPacket = new DatagramPacket(sendData, sendData.length, ip, port);
          clientSocket.send(sendPacket);
  
          // receive Message from other client
          try {
              receivePacket.setData(new byte[1024]);
              clientSocket.receive(receivePacket);
              System.out.println("REC: "
                      + new String(receivePacket.getData()));
  
          } catch (Exception e) {
              System.out.println("SERVER TIMED OUT");
          }
      }
  
      // close connection
      clientSocket.close();
  }
  </code></pre>
  
  <p><strong>UPDATE</strong>
  The code is generally working. I've tried it in two different home networks now and it's working. But it isn't working in my 3G or university network. In 3G, I verified that the NAT is mapping the two ports (the client port and by the router assigned port) together again, even after closing and opening the clientSocket. Has anyone an idea why it isn't working then? </p>