Appearance
Java IO - 06 UDP通信
本文主要介绍如何在Java中进行UDP通信,涉及的类包括DatagramSocket和DatagramPacket:

1. 案例一:一发一收
实现客户端发送一条消息,服务端接收到消息并显示出来。
首先编写服务端代码:
java
public static void main(String[] args) throws IOException {
// 1. 创建服务端程序,监听8888端口
DatagramSocket socket = new DatagramSocket(8888);
// 2. 创建数据包,用于接收数据
byte[] buffer = new byte[1024 * 64];
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
// 3. 接收数据(阻塞)
socket.receive(datagramPacket);
// 4. 处理数据
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
String str = new String(data, 0, length, Charset.forName("UTF-8"));
System.out.println(str);
// 5. 关闭资源
socket.close();
}然后编写客户端代码:
java
public static void main(String[] args) throws IOException {
// 1. 创建客户端程序
DatagramSocket socket = new DatagramSocket();
// 2. 准备数据包,该数据包包括服务端地址
byte[] bytes = "我是客户端".getBytes(Charset.forName("UTF-8"));
DatagramPacket datagramPacket = new DatagramPacket(
bytes,
bytes.length,
new InetSocketAddress("127.0.0.1", 8888)
);
// 3. 发送数据
socket.send(datagramPacket);
// 4. 关闭客户端
socket.close();
}2. 案例二:多发多收
实现客户端从控制台获取用户输入,并发送给服务端,服务端接收多条消息并显示出来。当用户输入exit时,退出客户端。
服务端代码:
java
public static void main(String[] args) throws IOException {
// 1. 创建服务端程序,监听8888端口
DatagramSocket socket = new DatagramSocket(8888);
// 2. 创建数据包,用于接收数据
byte[] buffer = new byte[1024 * 64];
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
while (true) {
// 3. 接收数据(阻塞)
socket.receive(datagramPacket);
// 4. 处理数据
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
InetAddress address = datagramPacket.getAddress(); // 获取客户端地址
int port = datagramPacket.getPort(); // 获取客户端端口
String str = new String(data, 0, length, Charset.forName("UTF-8"));
System.out.println(address.getHostAddress() + ":" + port + "发送:" + str);
}
}客户端代码:
java
public static void main(String[] args) throws IOException {
// 1. 创建客户端程序
DatagramSocket socket = new DatagramSocket();
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入:");
String input = scanner.nextLine();
if("exit".equals(input)){
// 4. 退出程序,关闭客户端
socket.close();
break;
}
// 2. 准备数据包,该数据包包括服务端地址
byte[] bytes = input.getBytes(Charset.forName("UTF-8"));
DatagramPacket datagramPacket = new DatagramPacket(
bytes,
bytes.length,
new InetSocketAddress("127.0.0.1", 8888)
);
// 3. 发送数据
socket.send(datagramPacket);
}
}在上面的服务端代码中,可以通过DatagramPacket获取客户端地址,这样服务端也可以给客户端发送消息。
首先客户端代码另开一个线程接收数据:
java
public class ClientDemo {
public static void main(String[] args) throws IOException {
// 1. 创建客户端程序
DatagramSocket socket = new DatagramSocket();
// 另开一个线程接收数据
new Thread(new Receive(socket)).start();
Scanner scanner = new Scanner(System.in);
while (true) {
String input = scanner.nextLine();
if ("exit".equals(input)) {
// 4. 退出程序,关闭客户端
socket.close();
break;
}
// 2. 准备数据包,该数据包包括服务端地址
byte[] bytes = input.getBytes(Charset.forName("UTF-8"));
DatagramPacket datagramPacket = new DatagramPacket(
bytes,
bytes.length,
new InetSocketAddress("127.0.0.1", 8888)
);
// 3. 发送数据
socket.send(datagramPacket);
}
}
}
@Slf4j
class Receive implements Runnable {
private DatagramSocket socket;
public Receive(DatagramSocket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
while (true) {
byte[] buffer = new byte[1024 * 64];
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
socket.receive(datagramPacket);
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
InetAddress address = datagramPacket.getAddress(); // 获取客户端地址
int port = datagramPacket.getPort(); // 获取客户端端口
String str = new String(data, 0, length, Charset.forName("UTF-8"));
log.info(address.getHostAddress() + ":" + port + " 返回:" + str);
}
} catch (IOException e) {
log.error("接收服务端消息异常:{}",e.getMessage());
}
}
}服务端代码在接收到客户端数据后,原样返回数据:
java
public class ServerDemo {
public static void main(String[] args) throws IOException {
// 1. 创建服务端程序,监听8888端口
DatagramSocket socket = new DatagramSocket(8888);
// 2. 创建数据包,用于接收数据
byte[] buffer = new byte[1024 * 64];
DatagramPacket datagramPacket = new DatagramPacket(buffer, buffer.length);
while (true) {
// 3. 接收数据(阻塞)
socket.receive(datagramPacket);
// 4. 处理数据
int length = datagramPacket.getLength();
byte[] data = datagramPacket.getData();
InetAddress address = datagramPacket.getAddress(); // 获取客户端地址
int port = datagramPacket.getPort(); // 获取客户端端口
String str = new String(data, 0, length, Charset.forName("UTF-8"));
System.out.println(address.getHostAddress() + ":" + port + " 发送:" + str);
// 5. 发送数据
socket.send(datagramPacket);
}
}
}