UDP Hole Punching on Android; UDP server

I'm currently trying to implement punching a UDD hole on Android for my udp server. Everything should work as follows:

  • The client (for nat, maybe 3G, ..) sends the DatagramPacket to the server (the server has a public ip; the port is also known as 45555). The client retries sending the datagram with the specified delay.
  • After the server receives a datagram, it sends datagrams ("signals") every 500 ms.
  • If the hole punching worked, the client should receive these signals.

Here is my current client implementation (Android):

//in onCreate() DatagramSocket socket = new DatagramSocket(46222); socket.setSoTimeout(2000); final Thread t = new Thread(new Runnable(){ @Override public void run() { int delay = Integer.parseInt(e2.getText().toString());//e1 and e2 are EditTexts String ip = e1.getText().toString(); try { DatagramPacket packet = new DatagramPacket(new byte[1],1, InetAddress.getByName(ip), 45555); while(!cleanUp){//cleanUp is set to true in onPause() lock.lock(); //Lock lock = new ReentrantLock(); socket.send(packet); lock.unlock(); Thread.sleep(delay); } } catch (Exception e) { e.printStackTrace(); }finally{ if(socket!=null) socket.close(); } } }); final Thread t2 = new Thread(new Runnable(){ @Override public void run() { try { Thread.sleep(1000); DatagramPacket packet = new DatagramPacket(new byte[1],1); while(!cleanUp){ lock.lock(); try{ socket.receive(packet); }catch(SocketTimeoutException e){ lock.unlock(); Thread.sleep(15); continue; } lock.unlock(); final String s = tv.getText().toString()+"signal\n"; MainActivity.this.runOnUiThread(new Runnable(){ @Override public void run() { tv.setText(s);//tv is a TextView } }); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); } finally{ if(socket!=null) socket.close(); } } }); //start both threads 

Here is the server implementation (Java):

 //int static void main(String[] args): final Thread t = new Thread(new Runnable(){ @Override public void run() { try { DatagramPacket packet = new DatagramPacket(new byte[1],1, addr, port); DatagramSocket socket = new DatagramSocket(); System.out.println("send"); while(true){ socket.send(packet); Thread.sleep(500); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); final Thread t2 = new Thread(new Runnable(){ @Override public void run() { try { DatagramPacket packet = new DatagramPacket(new byte[1],1); DatagramSocket socket = new DatagramSocket(45555); socket.receive(packet); addr = packet.getAddress(); //private static field InetAddress addr port = packet.getPort(); System.out.println(addr+":"+ packet.getPort()); //field int port t.start(); while(true){ socket.receive(packet); System.out.println("idle"); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }); t2.start(); 

Everything works when the client and server are on the same private network. To emulate a public server, I run the server-side code on my computer and configure the port on my router (which has a public ip) *. Clients will forward their packets to the public IP address of the router. But in both cases (my smartphone is connected to the Internet through my wlan / 3G or E network) no signals are received (the server receives client datagrams)

So why does the hole punching process not work?

considers

*: the router forwards any udp packets sent to its port 45555 to my computer

+5
source share
1 answer

Different sockets bind to a different private port and use different public ports of your NAT. You receive and send through different sockets. Send using the same socket through which you received the data. Else Your sending socket uses another public port on your router to send data to your NAT clients. This packet of your NAT clients drops because it comes from the same IP port but is unknown.

+3
source

All Articles