当前位置: 首页 > 知识库问答 >
问题:

Android上的UDP打孔;UDP服务器

邵奇
2023-03-14

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

  1. 客户端(在NAT之后;可能是3G,..)向服务器发送DatagramPacket(服务器有一个公共IP;端口也是45555)。客户端重复发送具有给定延迟的数据报
  2. 一旦服务器接收到数据报,它每500ms发送一次数据报(“信号”)。
  3. 如果穿孔成功,客户端应接收到这些信号

下面是我当前的客户端实现(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连接到internet)没有接收到信号(服务器接收到客户端的数据报)

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

共有1个答案

邓深
2023-03-14

不同的套接字绑定到不同的私有端口,并使用不同的NAT公共端口。您正在通过不同的套接字进行接收和发送。使用接收数据的相同套接字发送。另外,发送套接字使用路由器的不同公共端口向客户端NAT发送数据。客户端NAT丢弃此数据包,因为它来自相同得IP,但端口未知.

 类似资料:
  • stackoverflow用户! 我有一个必须处理p2p的应用程序,这就是我使用UDP打孔的方法。但我在执行上遇到了麻烦。希望你能给我一些提示。 我已经有了服务器,它运行得很好,可以把客户介绍给彼此,但是客户不能连接,可能是因为我使用套接字的经验不足。因此,客户端算法是: < li >创建udp套接字(socket(AF_INET,SOCK_DGRAM,IP proto _ UDP);) < li

  • 从server-A(可通过静态IP全局访问)开始,我将UDP套接字绑定到0.0.0.0:25000。 然后,在(住宅)NAT 后面使用客户端 A,我将 UDP 套接字绑定到 0.0.0.0:25000。然后,客户端 A 将数据包发送到服务器 A。 服务器 A 接收数据包。服务器 A 记录远程套接字 K,数据包从中 NAT 开始。服务器 A 向 K 发送数据包,目的是 NAT 将数据包转发到客户端

  • 程序代码 udp_server.php //创建Server对象,监听 127.0.0.1:9502端口,类型为SWOOLE_SOCK_UDP $serv = new Swoole\Server("127.0.0.1", 9502, SWOOLE_PROCESS, SWOOLE_SOCK_UDP); //监听数据接收事件 $serv->on('Packet', function ($serv,

  • 框架默认提供创建 TCP/UDP 服务的能力。只需要进行简易的配置,便可使用。 使用 TCP 服务 创建 TcpServer 类 <?php declare(strict_types=1); namespace App\Controller; use Hyperf\Contract\OnReceiveInterface; class TcpServer implements OnRecei

  • udp 服务端 udp 服务端 源码/* * Copyright (c) 2006-2018, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * *//** 程序清单:udp 服务端 * * 这是一个 udp 服务端的例程 * 导出 ud

  • 问题内容: 我试图在Java中实现UDP-Holepunching的简单草图以测试其概念,并稍后在我的C / C ++应用程序中使用它。 从Wikipedia来说,我的理解是:A和B是未定义网络结构背后的客户端,C是著名的公共可访问服务器。 A将数据包发送到服务器C,服务器保存其IP地址和端口。C将获得A的NAT的公共IP地址。这样做,A前面的NAT将创建一条路由,该路由会将此端口上的所有数据包传