DataOutputStream向客户端输出文本格式异常,Telnet显示错乱求助
Telnet连接Java服务器后出现奇怪缩进/字符异常问题
我正在开发一个通过localhost向连接客户端显示消息的Java服务器,使用Telnet连接后,输出文本出现奇怪的缩进和异常字符问题。
服务器代码:
private ServerSocket middleman; private int port = 8080; private Socket client; protected void createSocketServer() { try { while (true){ middleman = new ServerSocket(port); client = middleman.accept(); middleman.close(); PrintWriter out = new PrintWriter(client.getOutputStream(),true); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in)); String line; //Client stuff DataOutputStream dOut = new DataOutputStream(client.getOutputStream()); while((line = in.readLine()) != null) { System.out.println("echo: " + line); dOut.writeByte(1); dOut.writeUTF("Good day to you user. Here is a selection of poems " + "\n"); dOut.writeUTF("1. Cupcake Poem" + "\n"); dOut.flush(); //Response if(line.equals("cupcake")){ try{ FileReader fileReader = new FileReader(poem); BufferedReader bufferedReader = new BufferedReader(fileReader); StringBuffer stringBuffer = new StringBuffer(); String poemLine; while((poemLine = bufferedReader.readLine()) != null){ stringBuffer.append(poemLine); stringBuffer.append("\n"); } fileReader.close(); System.out.println("Contents of file:"); //System.out.println(stringBuffer.toString()); dOut.writeUTF(stringBuffer.toString()); dOut.flush(); } catch(IOException e){ e.printStackTrace(); } } else{ System.out.println("wrong!, the line is:" + line); } } } } catch(IOException e) { System.out.println(e); } }
现象:
客户端执行telnet localhost 8080后,输入“fish”,显示内容为:
[?]Good day to you user. here is a selection of poems 1. Cupcake Poem
输入“cupcake”时,虽能读取文件但存在奇怪的间距问题。请问这是否与Telnet有关?
问题根源分析
这个问题和Telnet有一定关联,但核心原因是你误用了二进制输出流处理纯文本协议:
DataOutputStream.writeUTF()的二进制特性:writeUTF()会先写入两个字节的长度前缀(用于标记后续UTF字符串的字节数),这两个二进制字节在Telnet(纯文本协议)中会被解析成乱码字符(比如你看到的[?]),同时打乱了文本的正常显示格式。- 混合使用两种输出流:你同时用
PrintWriter和DataOutputStream操作同一个Socket的输出流,这会导致流的缓冲和写入顺序混乱,进一步加剧显示异常。 - 换行符不匹配:Telnet默认期望换行符是
\r\n(回车+换行),而你代码里只用了\n,这会导致部分终端出现换行异常或缩进问题。
解决方案
你需要统一输出方式为纯文本模式,适配Telnet的文本协议特性,具体修改如下:
1. 移除DataOutputStream,只用PrintWriter处理文本输出
PrintWriter是专门为文本输出设计的类,自带缓冲和字符编码处理,完全适配Telnet的需求。
2. 统一使用\r\n作为换行符
替换所有\n为\r\n,确保Telnet终端能正确识别换行指令。
3. 删除二进制写入操作
去掉dOut.writeByte(1)这类二进制字节写入,避免产生乱码。
修改后的核心代码片段
protected void createSocketServer() { try { while (true){ middleman = new ServerSocket(port); client = middleman.accept(); middleman.close(); // 只保留PrintWriter,启用自动flush PrintWriter out = new PrintWriter(client.getOutputStream(), true); BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream())); String line; while((line = in.readLine()) != null) { System.out.println("echo: " + line); // 使用PrintWriter输出文本,换行用\r\n(println会自动添加) out.println("Good day to you user. Here is a selection of poems"); out.println("1. Cupcake Poem"); //Response if(line.equals("cupcake")){ try{ FileReader fileReader = new FileReader(poem); BufferedReader bufferedReader = new BufferedReader(fileReader); String poemLine; // 逐行输出文件内容,自动适配换行 while((poemLine = bufferedReader.readLine()) != null){ out.println(poemLine); } fileReader.close(); System.out.println("Contents of file sent to client"); } catch(IOException e){ e.printStackTrace(); out.println("Error loading poem: " + e.getMessage()); } } else{ System.out.println("wrong!, the line is:" + line); out.println("Wrong input! Please type 'cupcake' to get the poem."); } } } } catch(IOException e) { System.out.println(e); } }
额外提示
- 若需传输二进制数据,建议不要用Telnet作为客户端,改用专门的二进制客户端工具;
- Telnet客户端可能会自动转换换行符,但统一使用
\r\n能保证跨终端的兼容性; - 确保
poem变量指向正确的文件路径,避免文件读取异常。
内容的提问来源于stack exchange,提问作者Brock Lesnar
相关产品推荐
相关产品推荐

