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

TCP Socket编程:客户端无法接收服务器响应问题排查

TCP Socket客户端无法接收服务器响应问题排查

需求背景

我正在基于TCP Socket开发一个简单的客户端-服务器应用,服务器需根据收到的客户端消息做出对应响应,以此为用户提供交互接口。

问题现象

客户端无法接收服务器的响应,但服务器端调用PrintWriter.checkError()返回false,说明消息发送无错误触发。

排查猜想

我最初以为是服务器先发送响应,而客户端还未调用BufferedReader.readLine()阻塞等待,但考虑到TCP的FIFO异步特性,客户端无需立即读取消息,因此排除时序问题。

相关代码

客户端代码

public static void main(String args[]){        
    try{
        Socket socket = new Socket(this.getServerIp(),this.getTcpServPort());
        socket.setReuseAddress(true);
        //to get input from user
        BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
        //to send to server 
        PrintWriter out = new PrintWriter(socket.getOutputStream());
        //to receive from server)
        InputStreamReader in = new InputStreamReader(socket.getInputStream());
        BufferedReader brin = new BufferedReader(in);

             while(true){
             System.out.print("$");
             String str = new String();
             str = bf.readLine();
                if(str.equals("exit")){
                    break;
                }
             else if(str.equals("1")){
                     out.println(str);
                     out.flush();   
                     String resp;
                     //-> block and wait for response 
                     resp=brin.readLine();
                     if(resp==null){System.out.println("EOF");}
                     System.out.println(resp);
                 }   
                else{
                 System.out.println("Invalid command, type --help ");
             }  
            }//end of while 
       bf.close();
       in.close();
       brin.close();
       socket.close();
    }catch(IOException e){
        System.out.println(e.getMessage());
    }
}//end of main

服务端代码

public static void main(String args[]){ 
    try{
        ServerSocket serverSocket = new ServerSocket(servPort);
        
        Socket clSocket = serverSocket.accept();
        clSocket.setReuseAddress(true);

        InputStreamReader in = new InputStreamReader(clSocket.getInputStream()); 
        BufferedReader bf = new BufferedReader(in); 

        //newer
        PrintWriter out = new PrintWriter(clSocket.getOutputStream());

              while(true){ 
              String str=bf.readLine(); 
              System.out.println(str);             
              if(str.equals("exit")){ 
                break;
              }else if(str.equals("1")){ 
                  out.write("ack1"); 
                  out.flush();
                  System.out.println(out.checkError()); //false is normal
                  System.out.println("sent ack1");              
              }              
            }//end of while (hearing)
        out.close();
        clSocket.close(); 
        serverSocket.close();
        }catch(IOException e){
          System.out.println(e.getMessage());
        }//end of try-catch block      
}//end of main

问题

请问我遗漏了什么?


解决方案

核心问题是服务器发送响应时未添加换行符。

客户端通过brin.readLine()读取响应,该方法的逻辑是阻塞等待,直到读取到换行符(\n)或流终止。但服务端仅用out.write("ack1")发送了字符串内容,没有附加换行符,导致客户端的readLine()一直处于阻塞状态,无法返回结果。

修复方式(二选一)

  1. 使用PrintWriter的println()方法,它会自动在字符串末尾添加换行符:
    out.println("ack1");
    out.flush();
    
  2. 手动在响应字符串末尾添加换行符:
    out.write("ack1\n");
    out.flush();
    

额外优化建议

服务端处理str.equals("exit")前,建议先判断str是否为null。当客户端关闭连接时,bf.readLine()会返回null,直接调用equals()会触发空指针异常:

if (str == null || str.equals("exit")) {
    break;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 10:54:18