UDP 是一种无连接、不可靠传输的协议。
将数据源 IP、目的地 IP 和端口以及数据封装成数据包,大小限制在64KB内,直接发送出去即可。

快速入门

DatagramPacket:数据包对象
构造器:

  • public DatagramPacket(byte[] buf, int length, InetAddress address, int port):创建发送端数据包对象
    • buf:要发送的内容,字节数组
    • length:要发送内容的字节长度
    • address:接收端的 IP 地址对象
    • port:接收端的端口号
  • public DatagramPacket(byte[] buf, int length):创建接收端的数据包对象
    • buf:用来存储接收的内容
    • length:能够接收内容的长度

DatagramSocket:发送端和接收端对象
构造器:

  • DatagramSocket():创建发送端的 Socket 对象,系统会随机分配一个端口号。
  • DatagramSocket(int port):创建接收端的 Socket 对象并指定端口号

方法:

  • void send(DatagramPacket dp):发送数据包
  • void receive(DatagramPacket p):接收数据包

    1. public static void main(String[] args) throws Exception {
    2. System.out.println("===== 服务端启动 ======");
    3. // 1、创建接收端对象:注册端口
    4. DatagramSocket socket = new DatagramSocket(8888);
    5. // 2、创建一个数据包对象接收数据
    6. byte[] buffer = new byte[1024 * 64];
    7. DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
    8. // 3、等待接收数据。
    9. socket.receive(packet);
    10. // 4、取出数据即可
    11. // 读取多少倒出多少
    12. int len = packet.getLength();
    13. String rs = new String(buffer, 0, len);
    14. System.out.println("收到了:" + rs);
    15. // 获取发送端的ip和端口
    16. String ip = packet.getSocketAddress().toString();
    17. System.out.println("对方地址:" + ip);
    18. int port = packet.getPort();
    19. System.out.println("对方端口:" + port);
    20. socket.close();
    21. }
    1. public static void main(String[] args) throws Exception {
    2. System.out.println("===== 客户端启动 ======");
    3. // 1、创建发送端对象:发送端自带默认的端口号
    4. DatagramSocket socket = new DatagramSocket(6666);
    5. // 2、创建一个数据包对象封装数据
    6. /**
    7. * public DatagramPacket(byte buf[], int length, InetAddress address, int port)
    8. * 参数一:封装要发送的数据
    9. * 参数二:发送数据的大小
    10. * 参数三:服务端的主机IP地址
    11. * 参数四:服务端的端口
    12. */
    13. byte[] buffer = "Hello World 你好 世界".getBytes();
    14. DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
    15. InetAddress.getLocalHost(), 8888);
    16. // 3、发送数据出去
    17. socket.send(packet);
    18. socket.close();
    19. }

多发多收

  1. public static void main(String[] args) throws Exception {
  2. System.out.println("===== 服务端启动 ======");
  3. // 1、创建接收端对象:注册端口
  4. DatagramSocket socket = new DatagramSocket(8888);
  5. // 2、创建一个数据包对象接收数据
  6. byte[] buffer = new byte[1024 * 64];
  7. DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
  8. while (true) {
  9. // 3、等待接收数据。
  10. socket.receive(packet);
  11. // 4、取出数据即可
  12. // 读取多少倒出多少
  13. int len = packet.getLength();
  14. String rs = new String(buffer, 0, len);
  15. System.out.println("收到了来自:" + packet.getAddress() + ", 对方端口是" + packet.getPort() + "的消息:" + rs);
  16. }
  17. }
  1. public static void main(String[] args) throws Exception {
  2. System.out.println("===== 客户端启动 ======");
  3. // 1、创建发送端对象:发送端自带默认的端口号
  4. DatagramSocket socket = new DatagramSocket(7777);
  5. Scanner sc = new Scanner(System.in);
  6. while (true) {
  7. System.out.print("请说:");
  8. String msg = sc.nextLine();
  9. if ("exit".equals(msg)) {
  10. System.out.println("离线成功!");
  11. socket.close();
  12. break;
  13. }
  14. // 2、创建一个数据包对象封装数据
  15. byte[] buffer = msg.getBytes();
  16. DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
  17. InetAddress.getLocalHost(), 8888);
  18. // 3、发送数据出去
  19. socket.send(packet);
  20. }
  21. }

广播、组播

  • 单播:单台主机与单台主机之间的通信。
  • 广播:当前主机与所在网络中的所有主机通信。
  • 组播:当前主机与选定的一组主机的通信。

UDP 实现广播

  • 发送端发送的数据包的目的地写的是广播地址、且指定端口。 (255.255.255.255,9999)使用广播地址:255.255.255.255
  • 本机所在网段的其他主机的程序只要注册对应端口就可以收到消息了。(9999)

    1. public static void main(String[] args) throws Exception {
    2. System.out.println("===== 服务端启动 ======");
    3. // 1、创建接收端对象:注册端口
    4. DatagramSocket socket = new DatagramSocket(9999);
    5. // 2、创建一个数据包对象接收数据
    6. byte[] buffer = new byte[1024 * 64];
    7. DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
    8. while (true) {
    9. // 3、等待接收数据。
    10. socket.receive(packet);
    11. // 4、取出数据即可
    12. // 读取多少倒出多少
    13. int len = packet.getLength();
    14. String rs = new String(buffer, 0, len);
    15. System.out.println("收到了来自:" + packet.getAddress() + ", 对方端口是" + packet.getPort() + "的消息:" + rs);
    16. }
    17. }

    ```java public static void main(String[] args) throws Exception { System.out.println(“===== 客户端启动 ======”);

    // 1、创建发送端对象:发送端自带默认的端口号 DatagramSocket socket = new DatagramSocket(7777);

Scanner sc = new Scanner(System.in);
while (true) {
    System.out.print("请说:");
    String msg = sc.nextLine();

    if ("exit".equals(msg)) {
        System.out.println("离线成功!");
        socket.close();
        break;
    }

    // 2、创建一个数据包对象封装数据
    byte[] buffer = msg.getBytes();
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
                                               InetAddress.getByName("255.255.255.255"), 9999);

    // 3、发送数据出去
    socket.send(packet);
}

}


<a name="LS08R"></a>
### UDP 实现组播

- 发送端的数据包的目的地是组播 IP(例如:224.0.1.1,  端口:9999),组播地址:224.0.0.0 ~ 239.255.255.255
- 接收端必须绑定该组播 IP(224.0.1.1),端口还要注册发送端的目的端口 9999,这样即可接收该组播消息。
- DatagramSocket 的子类 MulticastSocket 可以在接收端绑定组播 IP。
```java
public static void main(String[] args) throws Exception {
    System.out.println("===== 服务端启动 ======");
    // 1、创建接收端对象:注册端口
    MulticastSocket socket = new MulticastSocket(9999);

    // 把当前接受端加入到一个组播组中
    // socket.joinGroup(InetAddress.getByName("224.0.0.1")); // Java 14 后过时
    socket.joinGroup(new InetSocketAddress(InetAddress.getByName("224.0.0.1"), 9999),
                     NetworkInterface.getByInetAddress(InetAddress.getLocalHost()));


    // 2、创建一个数据包对象接收数据
    byte[] buffer = new byte[1024 * 64];
    DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

    while (true) {
        // 3、等待接收数据。
        socket.receive(packet);
        // 4、取出数据即可
        // 读取多少倒出多少
        int len = packet.getLength();
        String rs = new String(buffer, 0, len);
        System.out.println("收到了来自:" + packet.getAddress() + ", 对方端口是" + packet.getPort() + "的消息:" + rs);
    }
}
public static void main(String[] args) throws Exception {
    System.out.println("===== 客户端启动 ======");

    // 1、创建发送端对象:发送端自带默认的端口号
    DatagramSocket socket = new DatagramSocket(7777);


    Scanner sc = new Scanner(System.in);
    while (true) {
        System.out.print("请说:");
        String msg = sc.nextLine();

        if ("exit".equals(msg)) {
            System.out.println("离线成功!");
            socket.close();
            break;
        }

        // 2、创建一个数据包对象封装数据
        byte[] buffer = msg.getBytes();
        DatagramPacket packet = new DatagramPacket(buffer, buffer.length,
                                                   InetAddress.getByName("224.0.0.1"), 9999);

        // 3、发送数据出去
        socket.send(packet);
    }
}