UDP(User Datagram Protocol,用户数据报协议)是一种无连接的传输层协议,位于IP协议之上。与TCP不同,UDP不提供可靠性保证、流量控制或拥塞控制机制,仅提供最基本的数据传输功能。

主要应用于语音通话,网络直播等

使用Java中的java.net.DatagramSocket

一、DatagramSocket:通信端点

DatagramSocket用于创建 UDP 通信的客户端或服务端套接字,负责数据的发送和接收。

构造器

构造器 说明
public DatagramSocket() 创建客户端的 Socket 对象,系统会随机分配一个端口号。
public DatagramSocket(int port) 创建服务端的 Socket 对象,并指定端口号。

常用方法

方法 说明
public void send(DatagramPacket dp) 发送数据包。
public void receive(DatagramPacket p) 接收数据包,该方法会阻塞直到有数据到达。

二、DatagramPacket:数据载体

DatagramPacket用于封装 UDP 通信中的数据,包括要发送或接收的字节数组、目标地址和端口等信息。

构造器

表格

构造器 说明
public DatagramPacket(byte[] buf, int length, InetAddress address, int port) 创建发送用的数据包对象,包含数据、目标 IP 和端口。
public DatagramPacket(byte[] buf, int length) 创建接收用的数据包对象,指定接收数据的缓冲区和长度。

常用方法

表格

方法 说明
public int getLength() 获取实际接收到的字节个数。

三、核心使用逻辑

  1. 服务端:使用带端口的DatagramSocket构造器创建套接字,然后调用receive()方法等待客户端数据。
  2. 客户端:使用无参DatagramSocket构造器创建套接字,构造包含目标信息的DatagramPacket,再调用send()方法发送。
  3. 数据交互:所有通信都基于数据包(DatagramPacket)进行,不建立持久连接。

案例:

多发一收

多发一收即多个客户端发送数据,一个服务端接受数据

客户端代码


import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.util.Scanner;


public class UdpClient {
    // 定义服务端的端口(建议和客户端端口区分开,避免冲突)
    private static final int SERVER_PORT = 10000;
    // 定义服务端的IP地址(本地测试用回环地址)
    private static final String SERVER_IP = "127.0.0.1";

    public static void main(String[] args) {
        // 1. 声明核心对象(Socket是UDP通信的端点,try-with-resources自动关闭Scanner)
        DatagramSocket clientSocket = null;
        try (Scanner scanner = new Scanner(System.in)) {

            // 2. 创建UDP客户端Socket(无参构造:系统自动分配随机端口)
            clientSocket = new DatagramSocket();
            System.out.println("UDP客户端已启动,可输入消息发送(输入exit退出)...");

            // 3. 循环接收用户输入并发送
            while (true) {
                // 提示用户输入
                System.out.print("请输入要发送的内容:");
                String inputData = scanner.nextLine().trim();

                // 4. 退出逻辑(关闭资源+终止循环,避免异常)
                if ("exit".equals(inputData)) {
                    System.out.println("用户主动退出,客户端正在关闭...");
                    break;
                }

                // 5. 空输入校验(提升用户体验)
                if (inputData.isEmpty()) {
                    System.out.println("输入内容不能为空,请重新输入!");
                    continue;
                }

                // 6. 封装UDP数据包(核心步骤:数据+目标地址+目标端口)
                // 6.1 把字符串转字节数组(UDP传输的是字节数据)
                byte[] dataBytes = inputData.getBytes();
                // 6.2 获取服务端的IP地址对象(127.0.0.1=本地回环地址)
                InetAddress serverAddress = InetAddress.getByName(SERVER_IP);
                // 6.3 创建数据包:包含要发送的数据、数据长度、服务端IP、服务端端口
                DatagramPacket sendPacket = new DatagramPacket(
                        dataBytes,       // 要发送的字节数据
                        dataBytes.length,// 数据长度
                        serverAddress,   // 目标IP地址
                        SERVER_PORT      // 目标端口
                );

                // 7. 发送数据包
                clientSocket.send(sendPacket);
                System.out.println("消息发送成功:" + inputData);
            }

        } catch (Exception e) {
            System.err.println("客户端发送消息出错:" + e.getMessage());
            e.printStackTrace();
        } finally {
            // 8. 最终关闭Socket(释放端口资源)
            if (clientSocket != null && !clientSocket.isClosed()) {
                clientSocket.close();
                System.out.println("客户端Socket已关闭,资源释放完成");
            }
        }
    }
}

服务端代码

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpServer {
    // 服务端监听端口(与客户端指定的服务端端口一致)
    private static final int SERVER_PORT = 10000;

    public static void main(String[] args) {
        DatagramSocket serverSocket = null;
        try {
            // 1. 创建服务端Socket并绑定端口
            serverSocket = new DatagramSocket(SERVER_PORT);
            System.out.println("UDP服务端启动,监听端口:" + SERVER_PORT);

            byte[] buffer = new byte[1024];
            DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

            // 2. 持续接收客户端消息
            while (true) {
                serverSocket.receive(packet); // 阻塞接收数据
                
                // 3. 解析客户端信息和消息
                InetAddress clientIp = packet.getAddress();
                int clientPort = packet.getPort();
                String msg = new String(packet.getData(), 0, packet.getLength());

                // 4. 输出核心信息
                System.out.println("客户端[" + clientIp + ":" + clientPort + "]:" + msg);
                
                // 重置数据包长度,避免残留数据
                packet.setLength(buffer.length);
            }
        } catch (IOException e) {
            System.err.println("服务端异常:" + e.getMessage());
        } finally {
            // 释放资源
            if (serverSocket != null && !serverSocket.isClosed()) {
                serverSocket.close();
            }
        }
    }
}

一发多收

代码同上,将客户端的while循环部分去除即可

使用IDEA多开测试即可本地测试

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐