本文目录导读:

在Java中实现UDP通信主要使用java.net.DatagramSocket和java.net.DatagramPacket这两个类,UDP是无连接的,发送方和接收方无需建立连接即可通信。
核心类说明
DatagramSocket:用于发送和接收UDP数据包的套接字DatagramPacket:表示数据包,包含数据、地址和端口信息
完整实现案例
UDP客户端(发送方)
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPClient {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
// 1. 创建DatagramSocket(无需指定端口,系统自动分配)
socket = new DatagramSocket();
// 2. 准备要发送的数据
String message = "你好,UDP服务器!";
byte[] sendData = message.getBytes("UTF-8");
// 3. 指定服务器地址和端口
InetAddress serverAddress = InetAddress.getByName("localhost");
int serverPort = 8888;
// 4. 创建数据包(数据、长度、地址、端口)
DatagramPacket packet = new DatagramPacket(
sendData,
sendData.length,
serverAddress,
serverPort
);
// 5. 发送数据包
socket.send(packet);
System.out.println("已发送消息: " + message);
// 6. 接收服务器响应(可选)
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 {
// 7. 关闭连接
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
}
UDP服务器(接收方)
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class UDPServer {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
// 1. 创建DatagramSocket并绑定到指定端口
socket = new DatagramSocket(8888);
System.out.println("UDP服务器已启动,端口: 8888");
byte[] buffer = new byte[1024];
// 2. 循环接收数据(使服务器持续运行)
while (true) {
// 3. 创建接收数据包
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
// 4. 接收客户端数据(阻塞方法)
socket.receive(packet);
// 5. 提取客户端信息
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
// 6. 解析接收到的数据
String receivedMessage = new String(
packet.getData(),
0,
packet.getLength(),
"UTF-8"
);
System.out.println("收到来自 " + clientAddress.getHostAddress() +
":" + clientPort + " 的消息: " + receivedMessage);
// 7. 发送响应给客户端
String response = "已收到消息: " + receivedMessage;
byte[] responseData = response.getBytes("UTF-8");
DatagramPacket responsePacket = new DatagramPacket(
responseData,
responseData.length,
clientAddress,
clientPort
);
socket.send(responsePacket);
System.out.println("已发送响应");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
}
简单单次通信版本
如果只需要发送一次消息就结束的场景:
精简客户端
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class SimpleUDPClient {
public static void main(String[] args) throws Exception {
try (DatagramSocket socket = new DatagramSocket()) {
String message = "Hello UDP";
DatagramPacket packet = new DatagramPacket(
message.getBytes(),
message.length(),
InetAddress.getLocalHost(),
9999
);
socket.send(packet);
}
}
}
精简服务器
import java.net.DatagramPacket;
import java.net.DatagramSocket;
public class SimpleUDPServer {
public static void main(String[] args) throws Exception {
try (DatagramSocket socket = new DatagramSocket(9999)) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
System.out.println(new String(packet.getData(), 0, packet.getLength()));
}
}
}
多线程版本(支持并发)
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class MultiThreadUDPServer {
public static void main(String[] args) throws Exception {
try (DatagramSocket serverSocket = new DatagramSocket(7777)) {
System.out.println("多线程UDP服务器启动,端口: 7777");
while (true) {
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
serverSocket.receive(packet);
// 为每个客户端创建新线程处理
new Thread(new ClientHandler(serverSocket, packet)).start();
}
}
}
}
class ClientHandler implements Runnable {
private DatagramSocket socket;
private DatagramPacket packet;
public ClientHandler(DatagramSocket socket, DatagramPacket packet) {
this.socket = socket;
this.packet = packet;
}
@Override
public void run() {
try {
String message = new String(packet.getData(), 0, packet.getLength(), "UTF-8");
InetAddress address = packet.getAddress();
int port = packet.getPort();
System.out.println(Thread.currentThread().getName() +
" 收到: " + message);
// 发送响应
String response = "已处理: " + message;
byte[] sendData = response.getBytes("UTF-8");
DatagramPacket sendPacket = new DatagramPacket(
sendData, sendData.length, address, port
);
socket.send(sendPacket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
运行步骤
- 先启动服务器:运行
UDPServer类 - 再启动客户端:运行
UDPClient类 - 观察控制台输出信息
关键点说明
| 特性 | 说明 |
|---|---|
| 无连接 | 发送前不需要建立连接 |
| 不可靠 | 数据可能丢失、重复或乱序 |
| 数据包大小 | 最大64KB(实际建议< 1472字节避免分片) |
| 速度快 | 比TCP少握手和确认过程 |
| 支持广播 | 可以发送到255.255.255.255或子网广播地址 |
常见问题
- 端口占用:如果出现
Address already in use,更换端口或等待端口释放 - 数据编码:建议统一使用UTF-8编码,避免乱码
- 接收缓冲区:
receive方法是阻塞的,直到收到数据才返回 - 数据边界:UDP保持消息边界,一次
send对应一次receive
这个实现可以满足大多数UDP通信场景,如实时游戏、视频流、DNS查询等。