
tcp echo 通信中 java 服务器无法回传消息的常见原因是 go 客户端向 java 服务器发送消息后阻塞在读取阶段,根本原因是 java 服务端使用 bufferedreader.readline() 等待换行符(\n 或 \r\n)作为输入终止标志,而 go 客户端未发送换行符,导致服务端始终阻塞在 readline() 调用中。
Java 的 BufferedReader.readLine() 是行缓冲读取方法,它会持续从输入流中读取字节,直到遇到换行符(\n、\r\n 或 \r)才返回当前行内容;若未收到换行符,则该方法将一直阻塞。而你的 Go 客户端代码中:
strEcho := "Hello" _, err = conn.Write([]byte(strEcho)) // ❌ 未包含换行符
仅发送了 "Hello" 字节序列(即 ['H','e','l','l','o']),没有 \n,因此 Java 服务端的 in.readLine() 永远不会返回,后续的 out.println(s) 也就不会执行——这正是客户端卡在 conn.Read() 前、看似“写成功但无响应”的根本原因。
✅ 正确做法是:确保 Go 客户端发送带换行符的字符串,与服务端 readLine() 行为严格匹配:
strEcho := "Hello\n" // ✅ 显式添加 '\n' // 或更健壮地使用 fmt.Fprintln: // import "fmt" // _, err = fmt.Fprintf(conn, "Hello\n")
同时,为提升健壮性,建议对 Java 服务端做两点优化:
立即学习“Java免费学习笔记(深入)”;
-
添加超时机制,避免单个异常连接长期占用线程:
clientSocket.setSoTimeout(30000); // 30秒读超时
-
显式刷新输出流(虽然 PrintWriter 构造时设 autoFlush=true 已覆盖此需求,但仍建议理解原理):
out.println(s); // 自动 flush(因构造时传入 true) // 等价于:out.print(s + "\n"); out.flush();
⚠️ 注意事项:
- 不要依赖 conn.Close() 触发刷新:PrintWriter 的 close() 会 flush,但 readLine() 阻塞在前,根本执行不到关闭逻辑;
- Go 中 conn.Read() 默认阻塞,需确保服务端已发送数据后再读;可考虑添加简单协议头或长度前缀用于生产环境;
- 若需支持多行交互,客户端应每次 Write 后都追加 \n,服务端循环体才能持续处理。
总结:TCP 文本协议通信必须保证收发两端的换行约定一致。readLine() ≠ “读任意字节”,而是“读一行”。修复只需一行改动——在 Go 客户端发送字符串末尾添加 \n,即可让 Java 服务端顺利解包、回显并返回,完成标准 Echo 流程。










