UDP打孔不能外部连接

时间:2015-01-01 10:38:11

标签: java networking udp hole-punching

我之前使用UDP打孔功能进行了一个简单的点对点聊天程序,现在我正在尝试做类似的事情,但是在使用libGDX制作的游戏中。游戏本身运行良好,连接在局域网上工作,但我很难尝试外部连接。我理解UDP穿孔的工作原理如下:

如果A人和B人都知道对方的IP地址和端口,那么:

  1. A向B发送UDP数据包,该数据包在A的NAT中打出一个洞但被B的防火墙丢弃
  2. A等待回复
  3. B向A发送一个UDP数据包,在自己的NAT中打出一个洞并通过A的防火墙
  4. B等待回复
  5. A接收B的初始消息并向B
  6. 发送第二条消息
  7. B收到A的消息
  8. 我的网络代码在一个类中:

    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");
    }
    

1 个答案:

答案 0 :(得分:0)

如果A和B都在同一个网络中,即如果它们在同一个LAN中,则A可以连接到B,反之亦然。你不需要在这里进行UDP打孔。

但是如果它们位于不同的网络中,或者位于不同的NAT后面,您可以尝试使用UDP打孔来实现直接连接。在这里,您需要一个中介服务器。并且A和B需要ping中介服务器,它将IP和端口号传递给其他相应的客户端。

最值得注意的是,并非所有NAT都支持打孔。这是NAT实现,主要是在公共领域不可用。因此,即使您使用UDP打孔,您也需要一个中继服务器作为后备。如果它没有打孔,中继服务器可以将消息传递给对方。

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

此链接说明了UDP Hole Punching架构。