确保 Java 不会在 PrinWriter.print() 完成之前关闭 OutputStream

Make sure Java will not close OutputStream before PrinWriter.print() finishes

我正在开发一个分布式系统,它通过 Socket 接收请求并使用 OutputStream 写回结果。

我遇到了问题,因为我必须 return 一个非常大的字符串,但是 Java 只是在我调用方法 print() 而没有完成打印后继续执行代码:

public void attendRequisition(Socket clientSocket) {
    PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());

    pw.print(getResults());

    pw.close()
}

一些信息:

我相信发生这种情况是因为 Java 认为方法 print() 已完成执行,但可能发生的情况是 Java 将消息发送到 JVM,然后 JVM 将其发送到网络适​​配器,并且由于消息非常大,在网络适配器能够发送整个消息之前调用 close() 方法。

我需要的是一种确保 Java 仅在打印过程完成且客户端收到整个消息后 运行 关闭指令的方法。

更新:我可以通过添加 Thread.sleep() 使其正常工作。通过这样做,SO 有足够的时间在 Java 关闭连接之前发送消息。但是我不想用这个方案,牵扯到太多问题。

我敢打赌,如果您使用另一个构造函数(即,其第二个参数是表示您希望刷新的布尔值的构造函数),那么您的示例将有效。您构建对象的方式禁用了自动刷新。

如果您的实际代码比较复杂,那么您可以在适当的时候调用 pw.flush()。

I can see the message coming and being cut becase of Java running the close() instruction

不,你不能。您可以看到消息被截断了,除非您对它的长度有误,但您却草率地得出了原因的结论。 Java 在完成发送之前不会关闭 PrintWriter。它将写入器刷新到套接字发送缓冲区,必要时阻塞,然后关闭底层套接字,该套接字在数据后面缓冲一个 FIN。在 FIN 到达之前,所有数据都被发送,所有数据都被接收,这向接收器发出流结束信号。

可能您没有意识到 PrintWriter 会吞噬异常,因此不应在网络上使用。

我能够使用 DataOutputStream.writeBytes() 解决问题。这样,只有当方法完成发送数据时,才会继续执行。它速度较慢,但​​有效。