Search code examples
javanetwork-programmingclient-serverp2phole-punching

I have been trying hole punching and send a datagram to my friends computer behind a router but nothing happens


I am trying to create a p2p connection. This is a just test app that i have check but seems like it does not work over internet. This is the java code that I am using on my pc to send a datagram to my friend: '

    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.*;
    import javax.net.ssl.SSLServerSocket;

    public class j2{


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

    InetAddress IPAddress = InetAddress.getByName("my friend's public IP"); 
    DatagramSocket clientSocket = new DatagramSocket(3456);


    System.out.println("Sending data");
    String datamsg = "hello ";
    byte[] sendData = datamsg.getBytes("UTF-8");
    byte [] receiveData = new byte[10];
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress,         7890);  

    int i = 500;
    //incase if some packets are lost
    while(i-->1)
    {
    clientSocket.send(sendPacket);
    }
    System.out.println("Data sent");

    System.out.println(clientSocket.isClosed());

    clientSocket.close();        



    }
    }

'

    //My friend uses this app to receive a data gram:
    // port 7890 is used to send data gram and create a hole. The same is used to     receice data.

'

    import java.io.IOException;
    import java.io.UnsupportedEncodingException;
    import java.net.*;
    import javax.net.ssl.SSLServerSocket;

    public class j1{


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

    InetAddress IPAddress = InetAddress.getByName("any ip"); //does not matter as it is used to open a hole
    DatagramSocket clientSocket = new DatagramSocket(7890);


    System.out.println("Sending data");
    String datamsg = "hello ";
    byte[] sendData = datamsg.getBytes("UTF-8");
    byte [] receiveData = new byte[10];
    DatagramPacket sendPacket = new DatagramPacket(sendData, sendData.length, IPAddress, 5000);  

    int i = 500;

    while(i-->1)
    {
    clientSocket.send(sendPacket);
    }
    System.out.println("Data sent");

    System.out.println(clientSocket.isClosed());



    DatagramPacket receivePacket = new DatagramPacket(sendData, sendData.length);                   

    clientSocket.receive(receivePacket);  

     System.out.println("Packet received");
     String msg = new String(receivePacket.getData());
    clientSocket.close();        

    }
    }'

    // I am not using a stun server as i already know my friends public ip address. We both have disabled our firewall as well.

Solution

  • Your approach is not the most reliable way to do NAT hole punching. At best it will "sometimes work".

    Here's some suggestions:

    • Don't hardcode port numbers. Let your UDP socket code pick a random port number (i.e. port=0) and use a STUN server (or equivalent) to ascertain your public IP address and public port mapping for this local socket.

    • Use a reliable service to exchange the IP/port. Since you are just trying to get a single packet to go through, start with using a phone to verbally exchange this information could suffice.

    • You don't need to send 500 packets all at once. The firewall code on the remote NAT might see this as a DOS attack and block everything. Try sending like 1 a second.

    • You should be simultaneously listening and sending periodic packets at the same time when trying to do the connectivity check that your code is doing. (e.g. two seperate threads or periodic polling).

    • Don't close the socket until after connectivity is confirmed by both endpoints. As you have it now, your first program closes the socket immediately after it sends the packet burst.

    • Read my full answer here: https://stackoverflow.com/a/8524609/104458