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()一直处于阻塞状态,无法返回结果。
修复方式(二选一)
- 使用
PrintWriter的println()方法,它会自动在字符串末尾添加换行符:out.println("ack1"); out.flush(); - 手动在响应字符串末尾添加换行符:
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
相关产品推荐
相关产品推荐

