-1

I have previously made a simple peer to peer chat program using UDP hole punching that worked and now I am trying to do something similar but within a game made using libGDX. The game itself runs fine and the connections work on a LAN but I have difficult trying with external connections. I understand how UDP hole punching works as follows:

If both person A and B know each other's IP addresses and ports then:

  1. A sends a UDP packet to B which punches a hole in A's NAT but is dropped by B's firewall
  2. A waits for a reply
  3. B sends a UDP packet to A which punches a hole in its own NAT and goes through A's firewall
  4. B waits for a reply
  5. A receives B's initial message and sends a second message to B
  6. B receives A's message

My networking code is in one class:

private boolean connected;
private DatagramSocket socket;
private DatagramPacket packet;

private InetAddress peerIP;

public NetworkManager(InetAddress peerIP){
    this.peerIP = peerIP;
    log("Created with peer ip: " + peerIP.getHostAddress());
    connected = false;
}

@Override
public void run(){
    try{
        log("Setting up socket");
        socket = new DatagramSocket(Constants.CLIENT_PORT);
        log("Socket successfully setup");

        //Punch hole
        log("Punching UDP Hole");
        sendBytes("one");

        //Receive
        log("Waiting for peer reply");
        receiveBytes(3);

        //Send second message 
        if(Arrays.equals(packet.getData(), "one".getBytes()) ){
            sendBytes("two");
        }

    }catch(Exception e){
        log("Error connecting to peer");
        return;
    } 

    log("Successfully connected");
    connected = true;
}


private synchronized void receiveBytes(int length) throws Exception {
    packet = new DatagramPacket(new byte[length], length);
    log("Receiving " + length + " bytes...");
    socket.receive(packet);
    log("Received bytes " + packet.getData()+ " from " + packet.getAddress());
}

private synchronized void sendBytes(String s) throws Exception {
    byte[] sendBytes = s.getBytes();
    packet = new DatagramPacket(sendBytes, sendBytes.length, peerIP, Constants.CLIENT_PORT);

    log("Sending " + sendBytes.length + " bytes...");

    socket.send(packet);

    log("Bytes sent");
}
Basim Khajwal
  • 946
  • 6
  • 6
  • "I have difficult trying with external connections.". Don't make us guess. What's not working>? What have you tried to resolve the issues? – The Archetypal Paul Jan 01 '15 at 10:42
  • I have tried getting some of my friends to run the program but it seems the hole punching doesn't work properly, even when I tried sending the packets manually – Basim Khajwal Jan 01 '15 at 10:55
  • What do you mean by "doesn't work properly"? Basically, you're just saying "it's not working" but not giving us any clue in what way it's not working. Can the routers be manually configured to let the packets through? Does your program then work? Are any messages getting through? – The Archetypal Paul Jan 01 '15 at 10:59
  • I haven't tried manually configuring them but I know that the packets are being sent, they are most likely being dropped by the peer's firewall. I assume there is an error with how I have interpreted the UDP hole punching. I had implemented this earlier almost exactly the same but for a simple chat program that worked so I still don't understand where this is going wrong. – Basim Khajwal Jan 01 '15 at 11:07
  • Please give us some information - otherwise we're just guessing. Unless more information is forthcoming, I won't be responding again. You need to help us to help you. – The Archetypal Paul Jan 01 '15 at 11:17
  • I just wanted to ask if there were any obvious errors in the code because it is definitely sending the packets and the sockets do work but my implementation must be wrong – Basim Khajwal Jan 01 '15 at 11:32
  • SO, you're still not providing more information, or trying out manual configuration to see where the problem might lie. I give up. – The Archetypal Paul Jan 01 '15 at 14:14

1 Answers1

0

If both A and B are in the same network, i.e if they are in the same LAN, A can connect to B and vice versa. You don't need UDP Hole punching here.

But if they are in different networks, or behind different NATs, you can try to achieve a direct connection using UDP hole punching. Here you need a mediator server. And A and B need to ping mediator server, which will pass the IP and port number to the other corresponding clients.

Most important point to note here is that not all NATs supports hole punching. It is upto the NAT implementation, which is mostly not available in public domain. So even if you use UDP Hole Punching, you need a relay server as a fallback. In case it doesn't get hole punched, the relay server can pass the messages to each other.

http://www.brynosaurus.com/pub/net/p2pnat/

This link explains UDP Hole Punching architecture.

Seema Kadavan
  • 2,538
  • 1
  • 16
  • 31
  • You don't necessarily need an mediator server. See the last paragraph of the Overview section here: http://en.wikipedia.org/wiki/UDP_hole_punching – The Archetypal Paul Jan 01 '15 at 16:18
  • There's an extensive answer to this question too: http://stackoverflow.com/questions/9656198/java-udp-hole-punching-example-connecting-through-firewall?rq=1 – The Archetypal Paul Jan 01 '15 at 16:20