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
相关产品推荐
相关产品推荐

