Android UDP广播与监听

发布于:2025-03-11 ⋅ 阅读:(27) ⋅ 点赞:(0)

在Android中,UDP广播和监听可以通过DatagramSocket和DatagramPacket来实现。UDP广播允许你将数据包发送到网络中的所有设备,而监听则允许你接收这些广播数据包。

1. 发送UDP广播
要发送UDP广播,你需要创建一个DatagramSocket,并使用DatagramPacket来封装要发送的数据。广播地址通常是255.255.255.255,或者子网广播地址(如192.168.1.255)。

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UdpBroadcastSender {

    private static final ExecutorService executorService = Executors.newCachedThreadPool();

    public static void sendBroadcast(String message, int port) {
        executorService.execute(() -> {
            DatagramSocket socket = null;
            try {
                // 创建DatagramSocket
                socket = new DatagramSocket();
                socket.setBroadcast(true);

                // 将消息转换为字节数组
                byte[] sendData = message.getBytes();

                // 创建DatagramPacket,指定广播地址和端口
                DatagramPacket sendPacket = new DatagramPacket(
                    sendData, sendData.length, 
                    InetAddress.getByName("255.255.255.255"), port
                );

                // 发送数据包
                socket.send(sendPacket);
                System.out.println("Broadcast message sent to: 255.255.255.255:" + port);
            } catch (Exception e) {
                System.err.println("Failed to send broadcast: " + e.getMessage());
            } finally {
                // 确保socket关闭
                if (socket != null && !socket.isClosed()) {
                    socket.close();
                }
            }
        });
    }

    public static void shutdown() {
        executorService.shutdown();
    }
}

2. 监听UDP广播
要监听UDP广播,你需要创建一个DatagramSocket并绑定到指定的端口。然后使用DatagramPacket来接收数据。

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class UdpBroadcastReceiver {

    private static final ExecutorService executorService = Executors.newCachedThreadPool();
    private DatagramSocket socket;
    private boolean isListening = false;

    public void startListening(int port, BroadcastListener listener) {
        executorService.execute(() -> {
            try {
                // 创建DatagramSocket并绑定到指定端口
                socket = new DatagramSocket(port);
                byte[] receiveData = new byte[1024];
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);

                isListening = true;
                while (isListening) {
                    // 接收数据包
                    socket.receive(receivePacket);

                    // 将接收到的数据转换为字符串
                    String message = new String(
                        receivePacket.getData(), 
                        0, 
                        receivePacket.getLength()
                    );

                    // 回调监听器
                    if (listener != null) {
                        String senderIp = receivePacket.getAddress().getHostAddress();
                        listener.onBroadcastReceived(message, senderIp);
                    }
                }
            } catch (Exception e) {
                System.err.println("UDP listening error: " + e.getMessage());
            } finally {
                stopListening();
            }
        });
    }

    public void stopListening() {
        isListening = false;
        if (socket != null && !socket.isClosed()) {
            socket.close();
        }
    }

    public static void shutdown() {
        executorService.shutdown();
    }

    // 定义回调接口
    public interface BroadcastListener {
        void onBroadcastReceived(String message, String senderIp);
    }
}

3. 在Android中使用

import android.os.Bundle;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity implements UdpBroadcastReceiver.BroadcastListener {

    private static final int UDP_PORT = 8888; // 自定义端口
    private UdpBroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 初始化UDP广播接收器
        receiver = new UdpBroadcastReceiver();

        // 开始监听广播
        receiver.startListening(UDP_PORT, this);

        // 发送广播
        UdpBroadcastSender.sendBroadcast("Hello from Android!", UDP_PORT);
    }

    @Override
    public void onBroadcastReceived(String message, String senderIp) {
        // 在主线程中更新UI
        runOnUiThread(() -> {
            Log.d("UDP_BROADCAST", "Received: " + message + " from " + senderIp);
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // 停止监听并关闭线程池
        receiver.stopListening();
        UdpBroadcastSender.shutdown();
        UdpBroadcastReceiver.shutdown();
    }
}

总结:
线程池管理

使用ExecutorService管理线程,避免频繁创建和销毁线程。

通过shutdown()方法优雅地关闭线程池。

资源释放:

在finally块中确保DatagramSocket关闭,避免资源泄漏。

回调机制:

通过BroadcastListener接口实现回调,解耦接收逻辑和UI更新。

动态停止监听:

提供stopListening()方法,支持动态停止UDP监听。

异常处理:

捕获并记录异常,确保程序在出现错误时不会崩溃。