确保 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()
}
一些信息:
- 我需要在发送结果后关闭连接。
- 如果没有close()指令,整个打印过程大约需要3~5秒才能完成
- 我正在使用 telnet 来测试这个方法,我可以看到由于 Java 运行关闭 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()
解决问题。这样,只有当方法完成发送数据时,才会继续执行。它速度较慢,但有效。
我正在开发一个分布式系统,它通过 Socket 接收请求并使用 OutputStream 写回结果。
我遇到了问题,因为我必须 return 一个非常大的字符串,但是 Java 只是在我调用方法 print() 而没有完成打印后继续执行代码:
public void attendRequisition(Socket clientSocket) {
PrintWriter pw = new PrintWriter(clientSocket.getOutputStream());
pw.print(getResults());
pw.close()
}
一些信息:
- 我需要在发送结果后关闭连接。
- 如果没有close()指令,整个打印过程大约需要3~5秒才能完成
- 我正在使用 telnet 来测试这个方法,我可以看到由于 Java 运行关闭 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()
解决问题。这样,只有当方法完成发送数据时,才会继续执行。它速度较慢,但有效。