You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java持久化TCP连接问题:客户端服务器二次通信无响应求助

问题分析与修复方案

嘿,我来帮你搞定这个TCP通信的问题!你的代码第一次通信正常,但第二次请求无响应的核心原因是服务器端的逻辑错误——它只处理了客户端的第一次请求,就回到等待新连接的状态,完全没管同一个连接的后续请求。

问题根源拆解

服务器的外层while(true)是用来监听新客户端连接的,但每次通过ss.accept()拿到客户端Socket后,你只执行了一次in.readLine()和out.writeBytes(),然后就直接回到外层循环等待下一个客户端了。这就导致:

  • 第一个客户端的连接在第一次通信后,服务器就不再监听它的后续数据
  • 客户端还在同一个连接上发送第二次请求,服务器根本没接收,客户端自然就挂起等待响应了

修复方案

我们需要让服务器在接受一个客户端连接后,持续处理该连接上的所有请求,直到客户端主动断开。同时优化客户端的小细节,提升代码效率。

修复后的服务器代码

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String args[]) throws IOException{
        ServerSocket ss = new ServerSocket(81);
        System.out.println("server started");
        while(true){
            System.out.println("waiting for client");
            Socket s = ss.accept();
            System.out.println("connected to client");
            
            // 为每个客户端连接创建单独的输入输出流
            BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
            DataOutputStream out = new DataOutputStream(s.getOutputStream());
            
            // 内层循环:持续处理该客户端的所有请求,直到连接断开
            try {
                String clientMsg;
                while ((clientMsg = in.readLine()) != null) {
                    System.out.println("recieved: " + clientMsg);
                    // 发送响应并立即刷新缓冲区,确保客户端能及时收到
                    out.writeBytes("200\n");
                    out.flush();
                }
            } catch (IOException e) {
                // 客户端断开连接时会抛出异常,这里处理关闭逻辑
                System.out.println("client disconnected");
            } finally {
                // 关闭资源
                s.close();
                in.close();
                out.close();
            }
        }
    }
}

优化后的客户端代码

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;

public class Client {
    public static void main(String[] args) throws UnknownHostException, IOException {
        Socket clientSocket = new Socket("localhost", 81);
        DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        System.out.println("connected to server");
        
        // 把Scanner移到循环外,避免重复创建对象
        Scanner sc = new Scanner(System.in);
        
        while (true) {
            System.out.println("enter data to send");
            String msg = sc.nextLine();
            // 发送请求并刷新缓冲区
            out.writeBytes(msg + "\n");
            out.flush();
            // 接收响应
            String response = in.readLine();
            if (response == null) {
                // 服务器断开连接时退出循环
                System.out.println("server disconnected");
                break;
            }
            System.out.println("response from server : " + response);
        }
        
        // 关闭资源
        sc.close();
        clientSocket.close();
        in.close();
        out.close();
    }
}

关键改动说明

  1. 服务器端:
    • 添加内层while循环,通过in.readLine()持续读取客户端的请求,直到客户端断开(readLine()返回null)
    • 增加异常捕获,处理客户端断开时的IO异常,确保资源能正确关闭
    • 每次发送响应后调用out.flush(),强制把缓冲区的数据发送出去,避免数据滞留
  2. 客户端:
    • 将Scanner的创建移到循环外部,避免每次循环都创建新对象,提升性能
    • 增加对in.readLine()返回null的判断,处理服务器断开的情况,避免无限等待

现在运行修复后的代码,你就可以在同一个连接上持续发送请求和接收响应啦!

内容的提问来源于stack exchange,提问作者Shubham Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:06:19