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编程工具,助力开发者即刻编程。

更多推荐