java - 无法使用Java DatagramSocket捕获UDP广播包

标签 java sockets networking udp datagram

我正在创建一个客户端-服务器通信应用程序,并且希望客户端能够自动检测并连接到服务器(假设它们位于同一网络上)。

以前,我的代码可以在 Linux 和 Windows 计算机上运行。我会广播一条简单的消息,并且可以阅读。我在使用 Wireshark 观察网络流量时也可以看到该消息。

我采取的方法是

  1. 获取服务器上网络上的广播地址。
  2. 在给定的持续时间内,广播一条消息(即将成为服务器 IP)
  3. 在客户端,等待收到消息。

我对网络还很陌生,因此任何明显的错误对我来说可能不会立即显而易见。

服务器广播代码:

public class Broadcaster {
    /* ... */
    public void pulse() throws InterruptedException, IOException, SocketException {
        Long elapsed = new Date().getTime();
        Long timeout = elapsed + this.duration;
        DatagramPacket packet = new DatagramPacket(this.message.getBytes(), this.message.length());
        HashSet<InetAddress> channels = Broadcaster.getBroadcastChannels();

        while(elapsed <= timeout) {
            for(InetAddress channel : channels) {
                DatagramSocket socket = new DatagramSocket(this.port);      
                socket.setBroadcast(true);
                socket.connect(channel, this.port);
                socket.send(packet);        
                System.out.println("Broadcast sent to " + channel.getHostAddress() + " (" + socket.getPort() + "): " + this.message);       
                socket.close();
            }   
            Thread.sleep(this.frequency);
            elapsed = new Date().getTime();
        }
    }

    private static HashSet<InetAddress> getBroadcastChannels() throws SocketException {
        /* Returns 192.168.0.255 */
    }

    public static void main(String[] args) {
        Broadcaster heart = new Broadcaster("Hello from the Raspberry Pi!", 120000, 5000, 8027);
        try {
            heart.pulse();
        } catch(SocketException e) {
            /* ...etc... */
        } finally {
            System.out.println("Broadcasting completed.");
        }
    }
}

客户端代码:

public class BroadcastListener {
    private int port;
    private int length;

    public BroadcastListener(int length, int port) {
        this.port = port;
        this.length = length;
    }

    public String getNext() throws IOException {
        byte buffer[] = new byte[this.length];  
        DatagramSocket socket = new DatagramSocket(this.port);
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length);  
        System.out.println("Waiting on " + socket.getLocalSocketAddress()); 
        socket.receive(packet);
        socket.close();

        return new String(buffer);
    }

    public static void main(String[] args) {
        System.out.println("Listening for network broadcasts...");
        BroadcastListener broadcast = new BroadcastListener(128, 8027);

        try {
            System.out.println("Received broadcast: " + broadcast.getNext());
        } catch(IOException e) {
            System.out.println("Could not receive broadcasts:");
            System.out.println(e.getMessage());
        }
    }
}

两台设备上看到的广播/网络掩码地址ifconfig输出为netmask 255.255.255.0广播192.168.0.255

最让我困惑的是,Wireshark 仍然可以看到广播,但当我运行客户端 Java 程序时,它只是位于 socket.receive(packet);

Wireshark screenshot on Imgur

客户端和服务器都在端口 8027 上。很明显,广播器正在工作,但客户端广播监听器没有工作。有人知道会发生什么吗?谢谢!

最佳答案

正如评论中提到的:检查你的防火墙:-)

我认识到的另一件事是,如果我用wireshark嗅探,则没有其他进程可以接收该数据报。意识到这一点后,我编写了一个nodejs脚本,默认情况下exclusive=false,但即使这样也没有帮助。也许有一个内核标志或其他东西,UDP 数据报不能被一个进程“消耗”。

关于java - 无法使用Java DatagramSocket捕获UDP广播包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20845008/

相关文章:

java - 我可以从 Axis2 Web 服务调用 Hadoop API 吗?

java - Neo4j:使用 XSD 强制架构

android - 使用 OkHttp 检查套接字是否连接或断开连接的更好方法?

http - 为什么一些互联网提供商关闭某些端口?

运行少量线程时 CPU 使用率达到 100%

java - 将数据从 JTable 导入到 Excel

java - JPA 查询中的语法错误

java - 如何使用 UDF DatagramSockets 协调发送和接收

c++ - 使用 winsock 设置主机名?

networking - Ambari 1.6.1 hadoop端口8088没有网站