当前位置: 首页 > news >正文

Android UDP广播与监听

在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监听。

异常处理:

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

相关文章:

  • 探索链表的奥秘:C语言中的查找操作与链表打印
  • 为什么要使用前缀索引,以及建立前缀索引:sql示例
  • python中如何把dataframe转换为列表及其性能比较
  • 【模拟CMOS集成电路设计】带隙基准(Bandgap)设计与仿真(基于运放的电流模BGR)
  • 【氮化镓】高输入功率应力诱导的GaN 在下的退化LNA退化
  • 【C】初阶数据结构9 -- 直接插入排序
  • Compose 实践与探索二 —— 状态订阅与自动更新1
  • Blueprint —— 蓝图技术指南
  • 初始化E9环境,安装Sqlserver数据库
  • 分布式事务的原理
  • 贪心算法精解:用C++征服最优解问题
  • 数据链路层 (以太帧 MAC地址 ARP协议)
  • 基于SpringBoot的手机销售网站设计与实现(源码+SQL脚本+LW+部署讲解等)
  • Liunx(CentOS-6-x86_64)使用Nginx部署Vue项目
  • 水下机器人推进器PID参数整定与MATLAB仿真
  • 同步模式之顺序控制,如何控制三个线程依次输出: abc abc abc abc abc?
  • 本地部署Navidrome个人云音乐平台随时随地畅听本地音乐文件
  • 无刷电动智能充气泵方案【天吉智芯】
  • 【软件逆向】QQ 连连看小游戏去广告与一键消除实现
  • 数据量过大的时候导出数据很慢
  • 台湾花莲县海域发生5.7级地震,震源深度15公里
  • 巴菲特股东大会精华版:批评拿贸易当武器,宣布年底交班
  • 五一假期前三日多景区客流刷新纪录,演艺、古镇、山水都很火
  • 客场不敌蓉城遭遇联赛首败,申花争冠需要提升外援能力
  • 人民日报:上海“模速空间”何以汇聚超百家大模型企业
  • 武汉大学新闻与传播学院已由“80后”副院长吴世文主持工作