本文目录导读:

在Java中,使用DatagramSocket发送UDP报文是一个常见的网络编程任务,下面我会详细解释如何实现,包括基本步骤、完整示例代码以及一些重要的注意事项。
基本步骤
- 创建
DatagramSocket对象(客户端可以指定端口或使用自动分配的端口) - 准备要发送的数据(字符串、二进制等)
- 创建
DatagramPacket数据包,包含数据、目标地址和端口 - 调用
send()方法发送数据包 - 关闭
DatagramSocket(可选)
完整示例代码
发送端(客户端)
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPSender {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
// 1. 创建DatagramSocket,不指定端口会自动分配一个可用端口
socket = new DatagramSocket();
// 2. 准备要发送的数据
String message = "Hello, UDP Server!";
byte[] sendData = message.getBytes("UTF-8"); // 指定字符编码,避免乱码
// 3. 指定目标地址和端口
InetAddress serverAddress = InetAddress.getByName("localhost"); // 或 IP 地址
int serverPort = 8888;
// 4. 创建DatagramPacket
DatagramPacket packet = new DatagramPacket(
sendData, // 数据字节数组
sendData.length, // 数据长度
serverAddress, // 目标地址
serverPort // 目标端口
);
// 5. 发送数据包
socket.send(packet);
System.out.println("UDP报文发送成功!");
// 可选:接收响应
// 准备接收缓冲区
byte[] receiveBuffer = new byte[1024];
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
socket.receive(receivePacket);
String response = new String(receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8");
System.out.println("收到服务器响应: " + response);
} catch (Exception e) {
e.printStackTrace();
} finally {
// 6. 关闭socket
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
}
接收端(服务器)
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPReceiver {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
// 1. 创建DatagramSocket并绑定到特定端口
socket = new DatagramSocket(8888);
System.out.println("UDP服务器启动,监听端口: 8888");
// 2. 准备接收数据的缓冲区
byte[] receiveBuffer = new byte[1024];
// 3. 创建接收数据包
DatagramPacket receivePacket = new DatagramPacket(receiveBuffer, receiveBuffer.length);
// 4. 接收数据(阻塞方法)
socket.receive(receivePacket);
// 5. 解析接收到的数据
String message = new String(receivePacket.getData(), 0, receivePacket.getLength(), "UTF-8");
InetAddress senderAddress = receivePacket.getAddress();
int senderPort = receivePacket.getPort();
System.out.println("收到来自 " + senderAddress.getHostAddress() + ":" + senderPort + " 的消息:");
System.out.println("消息内容: " + message);
// 6. 发送响应(可选)
String response = "消息已收到!";
byte[] responseData = response.getBytes("UTF-8");
DatagramPacket responsePacket = new DatagramPacket(
responseData,
responseData.length,
senderAddress,
senderPort
);
socket.send(responsePacket);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
}
重要注意事项
字符编码
- 始终指定字符编码(如
UTF-8),避免平台默认编码差异导致乱码
UDP的无连接特性
- UDP不保证数据包可靠到达
- 不保证数据包顺序
- 数据包可能丢失、重复或乱序
数据包大小限制
- UDP数据包最大理论大小为65535字节(64KB)
- 实际建议不超过1472字节(避免IP分片)
超时设置
// 设置接收超时(毫秒) socket.setSoTimeout(5000); // 5秒超时
广播发送
// 启用广播
socket.setBroadcast(true);
// 发送到广播地址
InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
// 或子网广播地址,如 192.168.1.255
发送自定义对象示例
// 序列化对象为字节数组发送 ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(yourObject); byte[] data = baos.toByteArray(); // 发送 DatagramPacket packet = new DatagramPacket(data, data.length, address, port); socket.send(packet);
简化版本(一行发送)
// 使用try-with-resources自动关闭
try (DatagramSocket socket = new DatagramSocket()) {
byte[] data = "Hello".getBytes("UTF-8");
socket.send(new DatagramPacket(data, data.length,
InetAddress.getByName("localhost"), 8888));
}
这个示例展示了UDP发送的基本模式,UDP适用于实时性要求高、可以容忍少量数据丢失的场景,如视频流、游戏、DNS查询等。