java - Android可以发送udp但不能接收

标签 java android sockets udp

我编写了一个基本的 udp 客户端服务器,其中一个 android 向服务器发送消息,然后服务器将其转发给其余客户端。

问题是,传入的 udp 消息到达服务器并且服务器将它们中继回去,但它们永远不会到达其余设备。

真正令人惊奇的是,如果我将服务器用作回显服务器(即仅中继到发件人),那么一切正常。所有客户端和服务器套接字都使用相同的端口 2706

服务器代码

while (true) {
    DatagramPacket packetToReceive = new DatagramPacket(new byte[2048], 2048);
    try {
        listenerSocket.receive(packetToReceive);
        InetAddress senderAddress = packetToReceive.getAddress();
        relayedBytes += packetToReceive.getLength();

        if (!connectedClients.contains(senderAddress)) {
            connectedClients.add(senderAddress);
        }

        for (InetAddress addr : connectedClients) {
            // commenting this line will make it an echo server
            if (!addr.equals(senderAddress))
            {
                //The following actually prints the ips of the android
                //devices so it knows where to send

                System.out.println(senderAddress.getHostAddress().toString() +
                    " to " + addr.getHostAddress().toString());
                byte[] data = packetToReceive.getData();
                packetToReceive.setData(data, 0, packetToReceive.getLength());
                packetToReceive.setAddress(addr);
                listenerSocket.send(packetToReceive);
            }
        }
    } catch (IOException) {
        e.printStackTrace();
    }
}

android 发送器逻辑:

mainSocket=new DatagramSocket(homePort);

//targetAddressString is the public IP of server
target = InetAddress.getByName(targetAddressString);
while (true) {
    byte[] data = getdata();
    if (data == null)
        continue;
    DatagramPacket packet = new DatagramPacket(data, data.length, target, targetPort);

    mainSocket.send(packet);
}

同时在其他线程上,接收者只是等待相同的 udp 套接字:

while (true) {
    Log.d("Player", "Waiting for data");
    DatagramPacket packet = new DatagramPacket(new byte[2048], 2048);
    try {
        mainSocket.receive(packet);
        Log.d("Player", "packet received");
        //do something with the packet
    } catch (IOException e) {
        e.printStackTrace();
    }
}

它永远不会比等待数据更进一步,因为它会阻塞直到它收到数据包

此外,我还可以在 wifi 和移动数据图标中看到它从未收到任何数据,但数据发送始终打开并且在服务器上看到收到

**编辑:-回声服务器**

while (true) {
    DatagramPacket receivedPacket = new DatagramPacket(new byte[2048], 2048);
    try {
        listenerSocket.receive(receivedPacket);
        InetAddress senderAddress = receivedPacket.getAddress();
        if (!connectedClients.contains(senderAddress)) {
            connectedClients.add(senderAddress);
        }

        for (InetAddress addr : connectedClients) {
            byte[] data = receivedPacket.getData();
            DatagramPacket sendPacket= new DatagramPacket(data,  0, receivedPacket.getLength(), addr, receivedPacket.getPort());
            listenerSocket.send(sendPacket);
        }
    } catch (IOException e) {
        // ...
    }
}

基本上,它应该将消息转发给曾经发送过任何数据的每个客户端,但不知何故它只将其发送给其原始发件人,其余客户端会错过它。代码在和我作对

最佳答案

这就是你想出来的NAT穿越问题。

这里有一些提示:

  1. 服务器可以硬编码为监听端口 2706。但它不应该对接收到的数据包的源端口有任何假设。从您的代码来看,您似乎从未尝试调用 setPort。因此,即使 NAT 没有以不同方式映射您的端口号,我也不确定您的原始代码是如何设置任何目标端口的。但我认为您是根据自己的答案和更新后的代码解决的。

  2. 不要在客户端套接字上硬编码客户端端口。在套接字上选择端口“0”(或不设置),让操作系统为您选择第一个可用端口。如果您在同一个 NAT 后面有多个客户端,此行为将允许更快的客户端重启、多个设备在同一个 NAT 后面,以及其他好处。

关于java - Android可以发送udp但不能接收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33715497/

相关文章:

java - Spring MVC - 多部分表单数据

java - 多模块项目的包 org.springframework.boot 不存在错误

android - 设计适合大文本用户的 android 布局

Android Retrofit 2 - 无法在 onResponse 回调中传递字符串

C# TCP Socket流消息困惑

java - 如何获取我在 jfilechooser 中选择的文件的路径?

java - 返回类型错误信息

java - 数组中的 Firebase 数据检索

android - 如何知道用户是否单击了微调器android

c++ - 将 IP 地址从 sockaddr 转换为 in_addr