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

Socket问题:仅在客户端终止时才能接收消息

问题根源

你的问题核心是BufferedReader的读取逻辑和客户端发送数据的方式不匹配:

  • BufferedReader.forEachLine会持续从输入流读取数据,直到流被关闭(客户端断开连接)才会结束循环。它的触发条件是读取到换行符(\n)或者流结束——如果客户端发送消息时没加换行,服务端的BufferedReader会一直缓存数据,直到客户端关闭连接(流触发EOF)才一次性输出所有内容。
  • 另外如果客户端使用PrintWriter或OutputStream发送数据时没调用flush(),消息会滞留在客户端的输出缓冲区,根本没发送到服务端。
解决办法

1. 客户端发送消息时添加换行符并刷新输出流

这是最直接的修复方式,确保客户端发送的每条消息末尾带上换行符,并且强制刷新输出缓冲区:

// 示例客户端发送代码
val output = PrintWriter(clientSocket.getOutputStream(), true) 
// 第二个参数autoFlush设为true,会自动在println后刷新
output.println("你好,服务端") // println自带换行符,满足服务端行读取的条件

// 或者手动控制的方式:
// val output = OutputStreamWriter(clientSocket.getOutputStream(), Charsets.UTF_8)
// output.write("你好,服务端\n")
// output.flush() // 必须手动刷新,否则消息会留在缓冲区

2. 服务端优化(可选)

如果不想依赖换行符,也可以改用指定长度的读取逻辑,但需要和客户端约定消息长度,实现起来更复杂。如果继续使用行读取,保持现有forEachLine逻辑即可,只要客户端配合发送换行符。

另外可以给服务端的资源管理加个优化,用use块自动关闭Socket:

private fun handleClient(member: Member) {
    try {
        member.clientSocket.use { socket -> // use块会自动关闭socket资源
            val reader = BufferedReader(InputStreamReader(socket.getInputStream(), Charsets.UTF_8))
            reader.forEachLine { line ->
                println("Message: $line")
            }
        }
    } catch(e: Exception) {
        e.printStackTrace()
    }
}
总结

只要让客户端发送消息时带上换行符并确保输出流被刷新,服务端就能在收到每条消息时立即打印,不用等到客户端关闭连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 09:34:58