Java UDP协议
UDP(User Datagram Protocol)是无连接、不可靠的传输层协议,适用于实时通信场景。
UDP特点
| 特点 | 说明 |
|---|---|
| 无连接 | 发送前不需建立连接 |
| 不可靠 | 不保证送达、不保证顺序 |
| 无流量控制 | 可能丢包 |
| 速度快 | 无握手开销 |
| 消息边界 | 每次发送一个完整消息 |
UDP vs TCP
| 特性 | UDP | TCP |
|---|---|---|
| 连接 | 无 | 三次握手 |
| 可靠性 | 不保证 | 保证 |
| 顺序 | 不保证 | 保证 |
| 开销 | 低 | 高 |
| 数据边界 | 有 | 流式 |
| 适用 | 实时通信 | 精确传输 |
核心类
| 类 | 作用 |
|---|---|
| DatagramSocket | UDP套接字,发送/接收 |
| DatagramPacket | UDP数据包 |
发送数据
Java
public class UdpSender {
public static void main(String[] args) throws IOException {
// 创建UDP套接字(不需要指定目标)
DatagramSocket socket = new DatagramSocket();
// 准备数据
String message = "Hello UDP";
byte[] data = message.getBytes();
// 创建数据包,指定目标地址和端口
InetAddress address = InetAddress.getByName("localhost");
int port = 8888;
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
// 发送
socket.send(packet);
System.out.println("已发送: " + message);
socket.close();
}
}
接收数据
Java
public class UdpReceiver {
public static void main(String[] args) throws IOException {
// 创建UDP套接字,绑定端口
DatagramSocket socket = new DatagramSocket(8888);
System.out.println("UDP接收端启动,监听8888端口");
// 准备接收缓冲区
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 接收数据(阻塞)
socket.receive(packet);
// 解析数据
String message = new String(packet.getData(), 0, packet.getLength());
InetAddress senderAddress = packet.getAddress();
int senderPort = packet.getPort();
System.out.println("收到: " + message);
System.out.println("来源: " + senderAddress + ":" + senderPort);
socket.close();
}
}
双向通信
Java
public class UdpChat {
public static void main(String[] args) throws IOException {
DatagramSocket socket = new DatagramSocket(8888);
byte[] buffer = new byte[1024];
// 接收线程
new Thread(() -> {
while (true) {
try {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
String msg = new String(packet.getData(), 0, packet.getLength());
System.out.println("收到: " + msg);
} catch (IOException e) {
break;
}
}
}).start();
// 发送线程
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
InetAddress targetAddress = InetAddress.getByName("localhost");
int targetPort = 9999;
while (true) {
String line = reader.readLine();
if ("quit".equals(line)) break;
byte[] data = line.getBytes();
DatagramPacket packet = new DatagramPacket(data, data.length, targetAddress, targetPort);
socket.send(packet);
}
socket.close();
}
}
DatagramPacket常用方法
Java
// 创建发送包
DatagramPacket packet = new DatagramPacket(data, data.length, address, port);
// 创建接收包
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 获取数据
byte[] data = packet.getData();
int length = packet.getLength(); // 实际数据长度
int offset = packet.getOffset(); // 数据偏移
// 获取来源信息
InetAddress address = packet.getAddress();
int port = packet.getPort();
// 设置目标
packet.setAddress(address);
packet.setPort(port);
packet.setData(data);
packet.setLength(length);
DatagramSocket常用方法
Java
DatagramSocket socket = new DatagramSocket(8888);
// 基本信息
int localPort = socket.getLocalPort();
InetAddress localAddress = socket.getLocalAddress();
// 超时设置
socket.setSoTimeout(3000); // 读超时3秒
// 缓冲区大小
socket.setSendBufferSize(64 * 1024);
socket.setReceiveBufferSize(64 * 1024);
// 广播支持
socket.setBroadcast(true);
// 状态
socket.isConnected(); // 是否已关联目标地址
socket.isClosed(); // 是否已关闭
// 绑定特定地址
socket.bind(new InetSocketAddress("192.168.1.1", 8888));
// 关闭
socket.close();
广播发送
Java
// 广播地址:255.255.255.255 或 子网广播地址
DatagramSocket socket = new DatagramSocket();
socket.setBroadcast(true);
String message = "Broadcast Message";
byte[] data = message.getBytes();
// 广播地址
InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
DatagramPacket packet = new DatagramPacket(data, data.length, broadcastAddress, 8888);
socket.send(packet);
socket.close();
适用场景
| 场景 | 说明 |
|---|---|
| 实时音视频 | 允许丢包,追求速度 |
| DNS查询 | 单次请求响应,无需连接 |
| 游戏同步 | 实时状态更新 |
| 日志收集 | 允许偶尔丢失 |
| 心跳检测 | 高频率小包 |
注意事项
UDP数据包大小有限制,超过MTU会被分片或丢弃
receive() 是阻塞方法,可设置超时
UDP不保证送达,应用层需自行实现重传(如DNS)
广播需要 setBroadcast(true)
DatagramPacket.getData() 返回整个缓冲区,需用 getLength() 获取实际长度
要点总结
- UDP无连接、不可靠、速度快
- 使用DatagramSocket发送/接收,DatagramPacket封装数据
- 发送需指定目标地址和端口,接收需绑定本地端口
- 适用于实时通信、DNS、游戏等场景
- 数据包有边界,每次发送/接收完整消息
📝 发现内容有误?点击此处直接编辑