Java Android上的UDP打孔;UDP服务器

Java Android上的UDP打孔;UDP服务器,java,android,network-programming,udp,hole-punching,Java,Android,Network Programming,Udp,Hole Punching,我目前正在尝试为我的udp服务器在Android上实现udp打孔。事情应该是这样的: 客户端(nat后面;可能是3G,…)向服务器发送数据包(服务器有一个公共ip;端口也被称为45555)。客户端以给定的延迟重复发送数据报 一旦服务器收到数据报,它每500毫秒发送一次数据报(“信号”) 如果打孔成功,客户应收到这些信号 以下是我当前的客户端实现(Android): 以下是服务器端实现(Java): 当客户机和服务器在同一个专用网络中时,一切都正常工作。为了模拟公共服务器,我在计算机上运行服务器端

我目前正在尝试为我的udp服务器在Android上实现udp打孔。事情应该是这样的:

  • 客户端(nat后面;可能是3G,…)向服务器发送数据包(服务器有一个公共ip;端口也被称为45555)。客户端以给定的延迟重复发送数据报
  • 一旦服务器收到数据报,它每500毫秒发送一次数据报(“信号”)
  • 如果打孔成功,客户应收到这些信号
  • 以下是我当前的客户端实现(Android):

    以下是服务器端实现(Java):

    当客户机和服务器在同一个专用网络中时,一切都正常工作。为了模拟公共服务器,我在计算机上运行服务器端代码,并在路由器上设置一个端口(具有公共ip)*。客户端将其数据包发送到路由器的公共ip。但在这两种情况下(我的智能手机通过wlan网络/3G或E连接到互联网),都没有收到任何信号(服务器接收客户端的数据报)

    那么,为什么打孔过程不起作用呢

    问候


    *:路由器会将发送到其端口45555的任何udp数据包转发到我的计算机

    不同的套接字绑定到不同的专用端口,并使用NAT的不同公共端口。您通过不同的套接字进行接收和发送。使用接收数据的同一套接字发送。否则,发送套接字将使用路由器的不同公共端口向客户端NAT发送数据。您的客户端NAT丢弃此数据包,因为它来自相同的IP但未知的端口。

    您所说的“在我的路由器上设置端口”是什么意思?你所做的不是打孔。穿孔用于在不同NAT后面的两个客户端之间建立对等连接。路由器将把发送到其端口45555的任何udp数据包转发到my computerThx,这应该是问题所在。但是,在服务器端,我希望同时接收和发送数据报。在JavaSocket中,有没有一种方法可以在同一个套接字(或使用同一端口)上同时发送和接收数据报?套接字是双向的,因此您可以同时发送和接收数据。但是您可能需要处理一个线程突然关闭套接字的情况。
        //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
    
    //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();