我正在尝试在Android上为我的udp服务器实现udp打孔.事情应该像这样:
客户端(在nat之后;可能是3G,...)向服务器发送DatagramPacket(服务器具有公共IP;端口也称为45555).客户端重复发送具有给定延迟的数据报
一旦服务器收到数据报,它就会每隔500毫秒发回一次数据报("信号").
如果打孔工作,客户应该接收这些信号
这是我当前的客户端实现(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
这是服务器端实现(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();
当客户端和服务器位于同一个专用网络中时,一切正常.为了模仿公共服务器,我在我的计算机上运行服务器端代码,并在我的路由器上设置一个端口(具有公共IP)*.客户端将其数据包发送到路由器的公共IP.但在这两种情况下(我的智能手机通过我的wlan网络/ 3G或E连接到互联网)没有收到信号(服务器接收客户端的数据报)
那么为什么打孔过程不起作用呢?
问候
*:路由器会将发送到其端口45555的任何udp数据包转发到我的计算机