当前位置: 首页 > article >正文

JavaEE 编写Java程序,实现简单的echo程序(网络编程TCP实践练习)

Java TCP 客户端/服务器开发深度解析

一、客户端代码全注释

public class TcpClient {
    private Socket socket = null;  // TCP通信核心对象

    // 构造函数:建立TCP连接
    public TcpClient(String ip, int port) throws IOException {
        // 创建Socket时会自动进行三次握手
        socket = new Socket(ip, port);  // 参数1: 服务器IP  参数2: 端口号
    }

    public void start() throws IOException {
        System.out.println("客户端启动");
        // try-with-resources 自动关闭资源
        try (InputStream in = socket.getInputStream();   // 接收数据的字节流
             OutputStream out = socket.getOutputStream(); // 发送数据的字节流
             Scanner scannerConsole = new Scanner(System.in); // 控制台输入
             Scanner scannerIn = new Scanner(in)) {      // 网络输入解析
            
            while (true) {
                // 1. 控制台输入处理
                System.out.print("-> ");
                String request = scannerConsole.next();  // 阻塞等待用户输入

                // 2. 发送请求到服务器
                PrintWriter printWriter = new PrintWriter(out); // 包装输出流
                printWriter.println(request);  // 自动添加换行符
                printWriter.flush();           // 强制立即发送缓冲区内容

                // 3. 接收服务器响应
                if (!scannerIn.hasNext()) break; // 检测连接是否关闭
                String response = scannerIn.next();
                System.out.println("服务器响应: " + response);
            }
        } // 自动关闭所有资源:socket、流、Scanner
    }
}

客户端核心三要素:

  1. 连接建立:通过new Socket()完成TCP三次握手
  2. 数据通道
    • getInputStream()获取接收数据流
    • getOutputStream()获取发送数据流
  3. 资源管理:使用try-with-resources自动释放连接

二、服务器代码全注释

public class TcpServer {
    private ServerSocket serverSocket = null;  // 服务端监听套接字

    // 初始化服务器
    public TcpServer(int port) throws IOException {
        serverSocket = new ServerSocket(port); // 绑定指定端口
        System.out.println("服务器监听端口: " + port);
    }

    public void start() throws IOException {
        System.out.println("启动服务器主线程");
        while (true) {
            // 阻塞等待客户端连接(核心方法)
            Socket clientSocket = serverSocket.accept(); 
            System.out.println("检测到新连接");

            // 为每个客户端创建独立线程
            new Thread(() -> {
                try {
                    processConnection(clientSocket); // 处理客户端业务
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    // 处理单个客户端连接
    private void processConnection(Socket clientSocket) throws IOException {
        // 获取客户端地址信息
        String clientInfo = String.format("[%s:%d]", 
            clientSocket.getInetAddress(), 
            clientSocket.getPort());
        
        try (InputStream inputStream = clientSocket.getInputStream();
             OutputStream outputStream = clientSocket.getOutputStream()) {
            
            Scanner scanner = new Scanner(inputStream);
            System.out.println(clientInfo + " 客户端上线");

            while (scanner.hasNext()) {  // 持续监听客户端请求
                // 1. 读取请求
                String request = scanner.next();
                
                // 2. 处理业务逻辑
                String response = process(request); 
                
                // 3. 返回响应
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                printWriter.flush();  // 确保数据立即发送
                
                System.out.println(clientInfo + " 处理请求: " + request);
            }
        }
        System.out.println(clientInfo + " 客户端下线");
    }

    // 业务处理(示例直接返回原字符串)
    private String process(String request) {
        return request.toUpperCase(); // 示例:转为大写
    }
}

服务器核心三要素:

  1. 端口监听ServerSocket绑定指定端口
  2. 连接接收accept()方法阻塞等待连接
  3. 并发处理:为每个客户端创建独立线程

三、关键方法深度解析

3.1 accept()方法详解

Socket clientSocket = serverSocket.accept();
  • 阻塞特性:在没有客户端连接时,线程会在此处挂起
  • 返回对象:返回的Socket对象包含:
    • 客户端IP地址(getInetAddress()
    • 客户端端口(getPort()
    • 新的数据通道(输入/输出流)
  • 并发基础:每次accept返回新的Socket,实现多客户端处理

3.2 flush()的必要性

printWriter.flush();
场景无flush有flush
数据传输时机缓冲区满时自动发送立即强制发送
适用场景大数据量传输需要实时交互的场景
风险点数据可能长时间滞留增加网络包数量

缓冲区原理

客户端内存:[数据1][数据2][数据3] → 缓冲区填满后自动发送
手动flush: [数据1] → 立即发送 → [数据2] → 立即发送

四、TCP核心组件对比

4.1 ServerSocket vs Socket

特性ServerSocketSocket
用途服务端监听端口建立实际数据通道
创建时机服务启动时创建accept()成功后自动创建
生命周期整个服务运行期间存在单个连接周期内存在
主要方法accept(), bind(), close()getInputStream(), close()

4.2 TCP通信全流程

客户端 服务器 SYN SYN-ACK ACK 三次握手完成 发送数据(request) 返回响应(response) FIN ACK FIN ACK 四次挥手断开 客户端 服务器

五、IntelliJ多实例运行配置

5.1 配置步骤演示

  1. 打开运行配置
    Run -> Edit Configurations
    
  2. 启用多实例
    选择客户端配置 -> Modify options -> Allow multiple instances
    
  3. 运行效果
    可以同时启动多个客户端进程
    每个进程独立连接到服务器
    

5.2 实现原理

  • JVM进程隔离:每个客户端运行在独立JVM中
  • 端口重用:客户端使用临时端口(1024-65535)
  • 服务端设计
    new Thread(() -> processConnection(clientSocket)).start();
    
    每个连接使用独立线程处理

六、最佳实践建议

  1. 资源关闭顺序

    // 正确关闭顺序示例
    try (Socket socket = new Socket(...);
         OutputStream out = socket.getOutputStream();
         InputStream in = socket.getInputStream()) {
        // 使用资源
    } // 自动反向关闭:in -> out -> socket
    
  2. 异常处理规范

    catch (IOException e) {
        System.err.println("连接异常: " + e.getMessage());
        // 需要手动关闭资源
        try {
            if (socket != null) socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
    
  3. 性能优化技巧

    • 使用线程池代替裸线程
    • 设置合理的Socket超时时间
    • 采用NIO非阻塞模式处理高并发

通过深入理解TCP通信机制和Java网络API的实现原理,开发者可以构建出稳定高效的网络应用程序。多线程服务器的设计需要特别注意资源竞争和线程安全问题,在实际生产环境中建议使用ExecutorService等高级并发工具进行线程管理。


http://www.kler.cn/a/562921.html

相关文章:

  • 解决Spring Boot中LocalDateTime返回前端数据为数组结构的问题
  • 欢乐力扣:最长连续序列
  • Flink SQL怎么用?
  • Android 10.0 Settings中系统菜单去掉备份二级菜单
  • 【字符串】最长公共前缀 最长回文子串
  • 2025最新Flask学习笔记(对照Django做解析)
  • windows设置暂停更新时长
  • 【多模态大模型】GLM-4-Voice端到端语音交互机器人VoiceAI
  • Ubuntu本地使用AnythingLLM
  • 【解决idea2024.3.3版本Vue插件报错】
  • 【新人系列】Python 入门专栏合集
  • 百度觉醒,李彦宏渴望光荣
  • 【Linux高级IO】掌握Linux高效编程:深入探索多路转接select机制
  • 3-提前结束训练
  • mac升级系统后聚焦Spotlight Search功能无法使用,进入安全模式可解
  • 【AIGC系列】3:Stable Diffusion模型介绍
  • 智慧物流小程序(论文源码调试讲解)
  • 最新版 (持续更新)docker 加速源 linux yum 源
  • 【Java企业生态系统的演进】从单体J2EE到云原生微服务
  • 现代前端框架渲染机制深度解析:虚拟DOM到编译时优化