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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:12:32