在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监听。
异常处理:
捕获并记录异常,确保程序在出现错误时不会崩溃。