Java UDP通信案例实现
UDP(User Datagram Protocol)是一种无连接的传输层协议,适合实时性要求高但可以容忍少量丢包的应用场景。

基础UDP通信实现
UDP发送端(客户端)
import java.net.*;
public class UDPSender {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
// 创建UDP套接字
socket = new DatagramSocket();
// 要发送的数据
String message = "Hello, UDP Server!";
byte[] sendData = message.getBytes();
// 指定接收方地址和端口
InetAddress address = InetAddress.getByName("localhost");
int port = 8888;
// 创建数据报包
DatagramPacket packet = new DatagramPacket(
sendData,
sendData.length,
address,
port
);
// 发送数据
socket.send(packet);
System.out.println("数据已发送: " + message);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
}
UDP接收端(服务器)
import java.net.*;
public class UDPReceiver {
public static void main(String[] args) {
DatagramSocket socket = null;
try {
// 创建UDP套接字并绑定到指定端口
socket = new DatagramSocket(8888);
System.out.println("UDP服务器已启动,等待接收数据...");
while (true) {
// 创建接收缓冲区
byte[] receiveData = new byte[1024];
DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length);
// 接收数据(阻塞方法)
socket.receive(packet);
// 提取数据
String message = new String(
packet.getData(),
0,
packet.getLength()
);
// 获取发送方信息
InetAddress senderAddress = packet.getAddress();
int senderPort = packet.getPort();
System.out.println("收到来自 " + senderAddress.getHostAddress() +
":" + senderPort + " 的数据: " + message);
// 可选:回复确认消息
String response = "消息已收到: " + message;
byte[] responseData = response.getBytes();
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();
}
}
}
}
双向通信示例
双向通信客户端
import java.net.*;
import java.util.Scanner;
public class UDPClient {
public static void main(String[] args) {
DatagramSocket socket = null;
Scanner scanner = new Scanner(System.in);
try {
socket = new DatagramSocket();
InetAddress serverAddress = InetAddress.getByName("localhost");
int serverPort = 9999;
// 启动接收线程
Thread receiveThread = new Thread(() -> {
try {
while (true) {
byte[] receiveData = new byte[1024];
DatagramPacket packet = new DatagramPacket(
receiveData,
receiveData.length
);
socket.receive(packet);
String message = new String(
packet.getData(),
0,
packet.getLength()
);
System.out.println("\n服务器回复: " + message);
System.out.print("请输入消息: ");
}
} catch (Exception e) {
// 套接字关闭时退出
}
});
receiveThread.start();
// 发送数据
while (true) {
System.out.print("请输入消息 (输入'quit'退出): ");
String message = scanner.nextLine();
if ("quit".equalsIgnoreCase(message)) {
break;
}
byte[] sendData = message.getBytes();
DatagramPacket packet = new DatagramPacket(
sendData,
sendData.length,
serverAddress,
serverPort
);
socket.send(packet);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
scanner.close();
}
}
}
双向通信服务器
import java.net.*;
import java.util.concurrent.ConcurrentHashMap;
public class UDPServer {
private static ConcurrentHashMap<String, ClientInfo> clients = new ConcurrentHashMap<>();
public static void main(String[] args) {
DatagramSocket socket = null;
try {
socket = new DatagramSocket(9999);
System.out.println("UDP服务器已启动,监听端口: 9999");
while (true) {
byte[] receiveData = new byte[1024];
DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length);
socket.receive(packet);
// 处理接收到的数据
String message = new String(
packet.getData(),
0,
packet.getLength()
);
InetAddress clientAddress = packet.getAddress();
int clientPort = packet.getPort();
String clientKey = clientAddress.getHostAddress() + ":" + clientPort;
// 保存客户端信息
clients.put(clientKey, new ClientInfo(clientAddress, clientPort));
System.out.println("收到客户端 [" + clientKey + "] 消息: " + message);
// 处理广播或单播
if (message.startsWith("@")) {
// 私聊功能
String[] parts = message.split(" ", 3);
if (parts.length >= 3) {
String targetKey = parts[0].substring(1);
String privateMessage = parts[2];
sendToClient(socket, targetKey, privateMessage);
}
} else {
// 广播消息
broadcast(socket, clientKey, message);
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
}
}
// 发送消息给指定客户端
private static void sendToClient(DatagramSocket socket, String clientKey, String message) {
ClientInfo client = clients.get(clientKey);
if (client != null) {
try {
byte[] data = message.getBytes();
DatagramPacket packet = new DatagramPacket(
data,
data.length,
client.address,
client.port
);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 广播消息给所有客户端
private static void broadcast(DatagramSocket socket, String sender, String message) {
String broadcastMessage = sender + ": " + message;
byte[] data = broadcastMessage.getBytes();
clients.forEach((key, client) -> {
try {
DatagramPacket packet = new DatagramPacket(
data,
data.length,
client.address,
client.port
);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
});
}
// 客户端信息类
static class ClientInfo {
InetAddress address;
int port;
ClientInfo(InetAddress address, int port) {
this.address = address;
this.port = port;
}
}
}
使用多线程处理多个客户端
import java.net.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class UDPThreadServer {
private static final int PORT = 7777;
private static ExecutorService threadPool = Executors.newFixedThreadPool(10);
public static void main(String[] args) {
DatagramSocket socket = null;
try {
socket = new DatagramSocket(PORT);
System.out.println("多线程UDP服务器已启动");
while (true) {
byte[] receiveData = new byte[1024];
DatagramPacket packet = new DatagramPacket(receiveData, receiveData.length);
socket.receive(packet);
// 将处理任务交给线程池
threadPool.execute(new ClientHandler(socket, packet));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (socket != null && !socket.isClosed()) {
socket.close();
}
threadPool.shutdown();
}
}
// 客户端处理器
static 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()
);
System.out.println("处理来自 " +
packet.getAddress().getHostAddress() + " 的消息: " + message);
// 处理业务逻辑...
String response = "处理完成: " + message.toUpperCase();
// 发送响应
byte[] responseData = response.getBytes();
DatagramPacket responsePacket = new DatagramPacket(
responseData,
responseData.length,
packet.getAddress(),
packet.getPort()
);
socket.send(responsePacket);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
UDP通信的注意事项
数据大小限制
// UDP数据包最大为65507字节(64KB减去UDP和IP头) // 实际应用中建议控制在1472字节以内(避免IP分片) int MAX_UDP_PACKET_SIZE = 1472; byte[] data = new byte[MAX_UDP_PACKET_SIZE];
超时设置
// 设置接收超时
socket.setSoTimeout(3000); // 3秒超时
try {
socket.receive(packet);
} catch (SocketTimeoutException e) {
System.out.println("接收超时");
}
端口复用
// 允许端口复用 socket.setReuseAddress(true);
广播地址
// 发送广播消息
socket.setBroadcast(true);
InetAddress broadcastAddress = InetAddress.getByName("255.255.255.255");
// 或者获取子网广播地址
// InetAddress broadcastAddress = InetAddress.getByName("192.168.1.255");
UDP vs TCP 选择建议
/* UDP适用场景: 1. 实时性要求高(视频通话、游戏) 2. 容忍少量丢包 3. 简单查询-响应模式 4. 多播或广播通信 TCP适用场景: 1. 数据完整性要求高 2. 大量数据传输 3. 需要可靠连接 4. 文件传输、网页浏览 */
运行示例
- 先运行UDPReceiver或UDPServer
- 再运行UDPSender或UDPClient
- 观察控制台输出
这个案例提供了UDP通信的完整实现,包括单向通信、双向通信、多客户端处理和线程池应用,你可以根据实际需求选择和修改相应的代码。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播