魔术桌
  • 更新日志
  • 新闻资讯
  • 数据资产
  • 网站导航
  • 订阅推荐
  • 商品推广
  • 日记
  • 摘录
  • 论文
  • 方案
  • 技术
  • 风格
  • 视觉
  • 原材料
  • 加工工艺
  • 元器件
  • 产品设备
  • 设计模式
  • 数据结构
  • 算法设计
  • 软件架构
  • 程序语言
  • 代码类库
  • 操作系统
  • 软件包
  • 健康
  • 环境
  • 社会
  • 道德
  • 法律
  • 经济
  • 政策
  • 更新日志
  • 新闻资讯
  • 数据资产
  • 网站导航
  • 订阅推荐
  • 商品推广
  • 日记
  • 摘录
  • 论文
  • 方案
  • 技术
  • 风格
  • 视觉
  • 原材料
  • 加工工艺
  • 元器件
  • 产品设备
  • 设计模式
  • 数据结构
  • 算法设计
  • 软件架构
  • 程序语言
  • 代码类库
  • 操作系统
  • 软件包
  • 健康
  • 环境
  • 社会
  • 道德
  • 法律
  • 经济
  • 政策
  • Language - Java - Java SE - API - 「java.net」

文章摘要: 提供实现网络操作相关的类。

介绍

简要说明

  • 提供了用于网络通信的类和接口。
  • 这个包支持多种网络协议,包括 TCP/IP 和 UDP,以及用于 URL 处理的类。

主要功能

  • URL 处理:提供了 URL 类来表示统一资源定位符,以及 URLConnection 类来处理与 URL 的连接。
  • Socket 编程:支持客户端和服务器端的 Socket 编程,包括面向连接的 TCP(通过 Socket 类)和面向无连接的 UDP(通过 DatagramSocket 类)。
  • 网络接口:提供了 InetAddress 类来表示互联网协议(IP)地址,以及 NetworkInterface 类来获取本地机器的网络接口信息。
  • HTTP 通信:提供了 HttpURLConnection 类,它支持 HTTP 特定的功能,如 GET 和 POST 请求。
  • 代理和隧道:支持使用代理服务器,以及通过代理服务器的隧道通信。
  • 多播数据报:支持多播通信,允许数据报被发送到多个目的地。

注意事项

  • 安全性:网络通信可能涉及敏感数据,因此需要使用 SSL/TLS 等加密协议来确保数据安全。
  • 异常处理:网络操作可能会抛出多种异常,如 IOException,因此需要妥善处理这些异常。
  • 资源管理:网络资源(如 Socket)在使用完毕后应正确关闭,以避免资源泄露。
  • 性能考虑:网络操作可能比本地操作慢,应考虑异步处理或使用连接池来提高性能。
  • 线程安全:某些网络类不是线程安全的,需要开发者注意并发访问的问题。

适用场景

  • 网络应用开发:任何需要网络通信的 Java 应用程序,如 Web 客户端、服务器端应用、网络服务。
  • 分布式系统:在分布式系统中,不同节点之间需要通过网络进行通信和数据交换。
  • 物联网(IoT):物联网设备之间通过网络进行数据传输和指令下发。
  • Web 服务:开发基于 HTTP 协议的 Web 服务客户端或服务器端。
  • 网络诊断工具:编写用于网络诊断的工具,如检查网络连接、获取网络信息等。

主要类和接口

InetAddress

表示互联网协议(IP)地址。

  • getByName(String host): 根据主机名获取 InetAddress 实例。
  • getAllByName(String host): 根据主机名获取 InetAddress 实例数组,用于处理主机名对应多个 IP 地址的情况。
  • getLocalHost(): 获取本地主机的 InetAddress 实例。
  • getHostAddress(): 返回 IP 地址字符串。

URL

表示统一资源定位符,它是一个指向互联网资源的指针。

  • openStream(): 打开到此 URL 的连接并返回一个用于从该连接读入的 InputStream。
  • openConnection(): 返回一个 URLConnection 对象,表示与 URL 引用的资源的通信链接。

URLConnection

抽象类,是所有类的超类,代表到 URL 引用的资源的连接。

  • connect(): 建立到远程对象的实际连接。
  • getInputStream(): 返回从此打开的连接读取的输入流。
  • getContent(): 获取此 URL 连接的内容。

HttpURLConnection

是 URLConnection 的子类,用于 HTTP 协议。

  • getResponseCode(): 获取服务器响应的状态码。
  • getResponseMessage(): 获取服务器响应的状态消息。
  • setRequestMethod(String method): 设置请求方法,如 “GET” 或 “POST”。

Socket

实现客户端套接字(也可以是服务器端),用于 TCP 网络通信。

  • connect(SocketAddress endpoint): 将此套接字连接到服务器。
  • getInputStream(): 返回此套接字的输入流。
  • getOutputStream(): 返回此套接字的输出流。
  • close(): 关闭此套接字。

ServerSocket

实现服务器端套接字,用于监听客户端的 TCP 连接请求。

  • bind(SocketAddress endpoint): 将 ServerSocket 绑定到指定的地址和端口。
  • accept(): 监听并接受到此套接字的连接。

DatagramPacket

表示数据报包,用于实现无连接的UDP网络通信。

  • getData(): 返回数据缓冲区。
  • setSocketAddress(SocketAddress address): 设置要发送或接收数据报的远程地址。

DatagramSocket

用于发送和接收 UDP 数据报包。

  • send(DatagramPacket p): 发送数据报包。
  • receive(DatagramPacket p): 从此套接字接收数据报包。

学习总结

  • 网络基础: java.net 包提供了网络编程的基础,包括 IP 地址、URL、套接字等。
  • URL处理: 使用 URL 和 URLConnection 可以轻松地读取网络资源。
  • HTTP协议: HttpURLConnection 提供了处理 HTTP 请求的方法,如设置请求方法、获取响应代码等。
  • 套接字编程: Socket 和 ServerSocket 用于实现基于 TCP 的客户端和服务器端通信。
  • 无连接通信: DatagramPacket 和 DatagramSocket 用于实现基于 UDP 的无连接通信。
  • 异常处理: 网络编程中可能会遇到多种异常,如 UnknownHostException, IOException 等,需要进行适当的异常处理。
  • 流操作: 网络通信涉及大量的流操作,需要熟悉 InputStream 和 OutputStream 的使用。
  • 线程安全: 网络操作可能是阻塞的,因此在多线程环境下使用时需要注意线程安全。
  • 资源管理: 使用完网络资源后,应该及时关闭套接字和流,以释放资源。

InetSocketAddress

  • 用于封装 IP 地址和端口号的类,它仅仅是一个地址信息的容器,本身不提供网络通信的功能。
  • 包路径:java.net.InetAddress

创建对象

  • 静态方法,无需实例化,即不需要通过new来创建对象。
方法返回值说明
InetAddress.getLocalHost()InetAddress获取本机IP,返回inetAddress对象
InetAddress.getByName(String host)InetAddress根据ip地址或域名,例如:"www.baidu.com"

相关方法

方法返回值说明
<InetAddress>.getHostName()String获取给ip地址对象中的主机名
<InetAddress>.getHostAddress()String获取该ip地址对象中的ip地址
<InetAddress>.isReachable(int timeout)boolean在指定的毫秒时间内判断主机与该ip对应的主机是否能连通

URL

  • 解析传入的RUL字符串,拆解得到:协议、域名、端口、请求资源。

  • 包路径:java.net.URL

  • 例子:http://www.baidu.com:80/index.html?name=xiaoming&age=18#a

方法返回值说明
new URL(String url)实例化
<URL>.getProtocol()返回协议,如http
<URL>.getHost()返回IP/域名,如www.baidu.com
<URL>.getPort()返回端口,如80
<URL>.getPath()返回请求资源,如/index.html
<URL>.getQuery()返回参数,如name=xiaoming&age=18
<URL>.getFile()返回请求资源和参数,如/index.html?name=xiaoming&age=18
<URL>.getRef()返回锚点,如a

TCP

相关信息

外部相关文章

内部相关文章

  • TCP详细总结:Technology-通信-协议-TCP

TCP流程图

Java8-API-Network-TCP协议的通讯流程

创建客户端

  • 包路径:java.net.Socket

客户端代码实现步骤

  1. 创建客户端的Socket对象,请求与服务端的连接。
  2. 使用Socket对象调用getOutputStream()方法得到字节输出流。
  3. 使用字节输出流完成数据的发送。
  4. 释放资源:关闭socket管道。

构造方法

方法说明
new Socket(String host, int port)指定的服务器IPhost和端口port,来请求与服务器与服务端建立连接,连接通过获得客户端Socket

相关方法

方法说明
<Socket>.getOutputStream()获得字节输出流对象OutputStream
<Socket>.getInputStream()获得字节输入流对象InputStream

客户端案例

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] ages) {
        try {
            // 创建服务端,并给指定 “服务端IP中的程序端口” 建立管道连接
            Socket socket = new Socket("127.0.0.1", 4545);
            System.out.println("客户端已启动");

            // 创建 “字节输出流” 来发送数据给服务端中的程序
            OutputStream os = socket.getOutputStream();
            // 将 “字节输出流” 包装成 “数据字节输出流” 对象
            DataOutputStream dos = new DataOutputStream(os);

            // 实例化接收用户输入
            Scanner scanner = new Scanner(System.in);

            while (true) {
                System.out.print(">>> ");
                // 接收用户输入
                String userInput = scanner.next();
                // 判断是否退出客户端
                if ("exit".equals(userInput)) {
                    // 释放 “数据字节输出流”
                    dos.close();
                    // 释放 “连接资源”
                    socket.close();
                    // 关闭客户端
                    System.out.println("客户端已关闭");
                    break;
                }
                // 开始写入数据
                dos.writeUTF(userInput);
                // 更新,防止存放在缓冲区没有真正发送出去
                dos.flush();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


}

创建服务端

  • 包路径:java.net.ServerSocket

服务端代码实现步骤

  1. 创建ServerSocket对象,注册服务端端口。
  2. 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。
  3. 通过Socket对象调用getInputStream()方法得到字节输入流,完成数据的接收。
  4. 释放资源,关闭socket管道。

构造方法

方法说明
new ServerSocket(int port)为服务端程序注册端口

相关方法

方法说明
<ServerSocket>.accept()阻塞等待客户端的连接请求,一旦与某个客户端成功连接,则返回服务端这边的Socket对象
<ServerSocket>.getRemoteSocketAddress()获得客户端的IP和端口

服务端案例

import java.io.IOException;
import java.io.InputStream;
import java.io.DataInputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 */
public class Server {
    public static void main(String[] ages) {
        try {
            // 创建服务端,并为服务端程序注册端口
            ServerSocket serverSocket = new ServerSocket(4545);
            System.out.println("服务端已启动");

            // 等待接收客户端的连接请求
            Socket socket = serverSocket.accept();

            // 使用 “字节输入流” 来接收客户端发送的数据
            InputStream is = socket.getInputStream();
            // 将 “字节输入流” 包装成 “数据字节输入流” 对象
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    // “解码” 接收到的客户端发送的数据
                    String data = dis.readUTF();

                    // 在控制台显示结果
                    System.out.print(socket.getRemoteSocketAddress() + " : ");
                    System.out.println(data);

                } catch (IOException e) {
                    // 当客户端程序关闭时,表示断开了连接
                    System.out.println("提示:客户端 \"" + socket.getRemoteSocketAddress() + "\" 已断开连接");
                    // 释放资源
                    dis.close();
                    socket.close();
                    // 关闭服务端
                    System.out.println("服务端已关闭");
                    break;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


}

案例 - TCP协议的多客户端同时通讯

  • 需要使用Java的多线程技术

客户端代码

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] ages) throws IOException {
        try {
            // 创建服务端,并给指定 “服务端IP中的程序端口” 建立管道连接
            Socket socket = new Socket("127.0.0.1", 4545);
            System.out.println("客户端已启动");

            // 创建 “字节输出流” 来发送数据给服务端中的程序
            OutputStream os = socket.getOutputStream();
            // 将 “字节输出流” 包装成 “数据字节输出流” 对象
            DataOutputStream dos = new DataOutputStream(os);

            // 实例化接收用户输入
            Scanner scanner = new Scanner(System.in);

            while (true) {
                System.out.print(">>> ");
                // 接收用户输入
                String userInput = scanner.next();
                // 判断是否退出客户端
                if ("exit".equals(userInput)) {
                    // 释放 “数据字节输出流”
                    dos.close();
                    // 释放 “连接资源”
                    socket.close();
                    // 关闭客户端
                    System.out.println("客户端已关闭");
                    break;
                }
                // 开始写入数据
                dos.writeUTF(userInput);
                // 更新,防止存放在缓冲区没有真正发送出去
                dos.flush();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


}

服务端代码

  • 服务端需要编写两个文件。

Server.java - 主线程代码

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * 服务端
 */
public class Server {
    public static void main(String[] ages) {
        try {
            // 创建服务端,并为服务端程序注册端口
            ServerSocket serverSocket = new ServerSocket(4545);
            System.out.println("服务端已启动");

            while (true) {
                // 等待接收客户端的连接请求
                Socket socket = serverSocket.accept();

                // 提示客户端与服务器建立连接
                System.out.println("消息:客户端 \"" + socket.getRemoteSocketAddress() + "\" 与服务器建立连接");

                // 将该客户端对象的socket通信管道,交给一个独立的线程负责处理
                new ServerReaderThread(socket).start();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}

ServerReaderThread.java - 多线程代码

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

public class ServerReaderThread extends Thread{
    private Socket socket;  // 全局变量,记录建立连接的客户端对象

    // 构造方法
    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }

    // 重写,执行核心代码
    @Override
    public void run() {
        try {
            // 使用 “字节输入流” 来接收客户端发送的数据
            InputStream is = socket.getInputStream();
            // 将 “字节输入流” 包装成 “数据字节输入流” 对象
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    // “解码” 接收到的客户端发送的数据
                    String data = dis.readUTF();

                    // 在控制台显示结果
                    System.out.print(socket.getRemoteSocketAddress() + " : ");
                    System.out.println(data);

                } catch (IOException e) {
                    // 当客户端程序关闭时,表示断开了连接
                    // 释放资源
                    dis.close();
                    socket.close();
                    // 关闭当前服务端线程
                    System.out.println("提示:客户端 \"" + socket.getRemoteSocketAddress() + "\" 已断开连接,关闭对该客户端的服务进程");
                    break;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

案例 - TCP协议的端口转发技术实现群聊

客户端代码

客户端代码 - 主进程

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;

/**
 * 客户端
 */
public class Client {
    public static void main(String[] ages) throws IOException {
        try {
            // 创建客户端,并给指定 “服务端IP中的程序端口” 建立管道连接
            Socket socket = new Socket("127.0.0.1", 4545);
            System.out.println("客户端已启动");

            // 创建独立下线程,来接收服务端发送过来的消息
            new ClientReaderThread(socket).start();

            // 创建 “字节输出流” 来发送数据给服务端中的程序
            OutputStream os = socket.getOutputStream();
            // 将 “字节输出流” 包装成 “数据字节输出流” 对象
            DataOutputStream dos = new DataOutputStream(os);

            // 实例化接收用户输入
            Scanner scanner = new Scanner(System.in);

            while (true) {
                System.out.print(">>> ");
                // 接收用户输入
                String userInput = scanner.next();
                // 判断是否退出客户端
                if ("exit".equals(userInput)) {
                    // 释放 “数据字节输出流”
                    dos.close();
                    // 释放 “连接资源”
                    socket.close();
                    // 关闭客户端
                    System.out.println("客户端已关闭");
                    break;
                }
                // 将数据 “编码” 成UTF-8,并发送给服务端
                dos.writeUTF(userInput);
                // 更新,防止存放在缓冲区没有真正发送出去
                dos.flush();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


}

客户端代码 - 子进程

  • 用于不断接收服务器发来的信息
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;

/**
 * 客户端线程
 */
public class ClientReaderThread extends Thread {
    private Socket socket;

    // 构造方法
    public ClientReaderThread(Socket socket) {
        this.socket = socket;
    }

    // 重写,执行核心代码
    @Override
    public void run() {
        try {
            // 使用 “字节输入流” 来接收服务器发送的数据
            InputStream is = socket.getInputStream();
            // 将 “字节输入流” 包装成 “数据字节输入流” 对象
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    // “解码” 接收到的服务端发送的数据
                    String data = dis.readUTF();

                    // 在控制台显示结果
                    System.out.println(data);

                } catch (IOException e) {
                    // 当客户端程序关闭时,表示断开了连接
                    // 释放资源
                    dis.close();
                    socket.close();
                    break;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

服务端代码

服务端代码 - 主进程

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;

/**
 * 服务端
 */
public class Server {

    // 创建存储与服务器连接的客户端Socket对象的集合
    public static List<Socket> onLineSockets = new ArrayList<>();

    public static void main(String[] ages) {
        try {
            // 创建服务端,并为服务端程序注册端口
            ServerSocket serverSocket = new ServerSocket(4545);
            System.out.println("服务端已启动");

            while (true) {
                // 等待接收客户端的连接请求
                Socket socket = serverSocket.accept();
                // 将客户端对象添加到集合中
                onLineSockets.add(socket);

                // 提示客户端与服务器建立连接
                System.out.println("消息:客户端 \"" + socket.getRemoteSocketAddress() + "\" 与服务器建立连接");

                // 将该客户端对象的socket通信管道,交给一个独立的线程负责处理
                new ServerReaderThread(socket).start();
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}

服务端代码 - 子进程

  • 用于处理客户端发来的信息,并将信息同步发送给其他在线的客户端
import java.io.*;
import java.net.Socket;

/**
 * 服务端线程
 */
public class ServerReaderThread extends Thread {
    private Socket socket;

    // 构造方法
    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }

    // 重写,执行核心代码
    @Override
    public void run() {
        try {
            // 使用 “字节输入流” 来接收客户端发送的数据
            InputStream is = socket.getInputStream();
            // 将 “字节输入流” 包装成 “数据字节输入流” 对象
            DataInputStream dis = new DataInputStream(is);

            while (true) {
                try {
                    // “解码” 接收到的客户端发送的数据
                    String data = dis.readUTF();

                    // 在控制台显示结果
                    System.out.println(socket.getRemoteSocketAddress() + " : " + data);

                    // 将客户端发送的信息,同步发送给其他有建立连接的客户端
                    sendMsgToAll(data);

                } catch (IOException e) {
                    // 当客户端程序关闭时,表示断开了连接
                    // 释放资源
                    dis.close();
                    socket.close();
                    // 更新存放客户端集合,将当断开连接的客户端在集合中删除掉
                    Server.onLineSockets.remove(socket);
                    // 关闭当前服务端线程
                    System.out.println("提示:客户端 \"" + socket.getRemoteSocketAddress() + "\" 已断开连接,关闭对该客户端的服务进程");
                    break;
                }
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    // 同步发送信息给其他客户端
    private void sendMsgToAll(String data) throws IOException {
        for (Socket onLineSocket : Server.onLineSockets) {

            // 判断该消息是否是当前客户端发送来,即不需要给当前客户端再发信息回去
            if (socket == onLineSocket) {
                continue;
            }
            // 创建 “字节输出流” 来发送数据给客户端
            OutputStream os = onLineSocket.getOutputStream();
            // 将 “字节输出流” 包装成 “数据字节输出流” 对象
            DataOutputStream dos = new DataOutputStream(os);

            // 将数据 “编码” 成UTF-8,并发送给服务端
            dos.writeUTF(data);
            // 更新,防止存放在缓冲区没有真正发送出去
            dos.flush();
        }

    }


}

UDP

相关信息

外部相关文章

内部相关文章

  • UDP详细总结:Technology-通信-协议-UDP

相关信息

流程图

Java8-API-Network-UDP协议的通信流程

创建客户端、服务端

  • java.net.DatagramSocket

构造方法

方法说明
new DatagramSocket()创建客户端的Socket对象,系统随即分配一个端口号
new DatagramSocket(int port)创建服务端的Socket对象,并指定端口号

相关方法

方法说明
<DatagramSocket>.send(DatagramSocket dp)发送数据包
<DatagramSocket>.receive(DatagramSocket p)使用数据包接收数据
<DatagramSocket>.close()关闭客户端对象

创建数据包

  • java.net.DatagramPacket

构造方法

方法说明
new DatagramPacket(byte[] buf, int length, InetAddress address, int port)创建用于发送数据的数据包对象,buf字节数据包、length数据包的字节长度、address接收端的IP地址、port接收端的端口号
new DatagramPacket(byte[] buf, int length)创建用来接收数据的数据包对象,buf存放接收到的数据包字节数组大小、length接收到的数据包字节数组长度

相关方法

方法说明
<DatagramPacket>.getLength()获取数据包,实际接收到的字节个数

案例

客户端代码

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

/**
 * 客户端
 */
public class Client {
    public static void main(String[] ages) throws IOException {
        // 实例化一个客户端对象
        DatagramSocket socket = new DatagramSocket(8888);
        System.out.println("客户端已启动");

        // 创建字节输出流对象
        FileOutputStream fos = new FileOutputStream("webapps/pages/login.html");
        // 包装成数据流
        DataOutputStream dos = new DataOutputStream(fos);



        // 将需要发送的数据进行“编码”,转换成字节码
        byte[] dataByte = new;

        // 实例化数据包对象,用于封装要发出去的数据(将要发出去的字节数据、字节数据的长度、接收端)
        DatagramPacket packet = new DatagramPacket(dataByte, 0, dataByte.length, new InetSocketAddress("127.0.0.1", 9999));

        // 开始将数据包发送到服务端,阻塞
        socket.send(packet);

        // 释放资源,即关闭客户端
        socket.close();

    }


}

服务端代码

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

/**
 * 服务端
 */
public class Server {
    public static void main(String[] ages) throws IOException {
        // 实例化一个服务端对象
        DatagramSocket socket = new DatagramSocket(9999);

        System.out.println("启动服务端");

        // 创建存放接收数据包的字节数组,大小为64kb
        byte[] dataByte = new byte[1024 * 64];
        // 实例化一个数据包对象,用于接收数据
        DatagramPacket packet = new DatagramPacket(dataByte, 0, dataByte.length, new InetSocketAddress("127.0.0.1", 8888));

        while (true) {
            // 开始使用数据包来接收客户端发来的数据
            socket.receive(packet);

            // 获取本次数据包中接收到了多少字节数组
            int len = packet.getLength();

            // 将接收到的数据进行“解码”,转换成字符串
            String data = new String (dataByte, 0, len);

            // 在控制台输出接收到的数据
            System.out.println(packet.getAddress().getHostAddress() + " : " + data);
            System.out.println("-------------------------");
        }

    }

}

更新时间: 2025/11/16 17:17