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

时间:2017-07-04 23:23:48

标签: java sockets outputstream

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

我遇到了问题,因为我必须返回一个非常大的字符串,但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只在打印过程完成并且客户端收到整个消息后才运行指令close()的方法。

更新:通过添加Thread.sleep(),我能够正常运行。通过这样做,SO有足够的时间在Java关闭连接之前发送消息。但我不想使用这个解决方案,它涉及太多问题。

3 个答案:

答案 0 :(得分:0)

我能够使用DataOutputStream.writeBytes()解决问题。这样,执行仅在方法完成发送数据时继续。它比较慢,但有效。

答案 1 :(得分:-1)

我敢打赌,如果你使用另一个构造函数(即第二个参数是布尔值来表示你想要刷新的那个)那么你的例子就可以了。你构建对象的方式是autoflush被禁用。

如果您的真实代码更复杂,那么您可以在适当的时刻调用pw.flush()。

答案 2 :(得分:-1)

  

由于Java运行close()指令,我可以看到消息即将被删除

不,你不能。你可以看到被删除的信息,除非你对它有多长时间存在错误,但你会对原因做出结论。 Java在完成发送之前不会关闭PrintWriter。它将编写器刷新到套接字发送缓冲区,必要时阻塞,然后关闭底层套接字,后者在数据后面缓冲FIN。在FIN到达之前,所有数据都被发送,并且所有数据都被接收,这将信号流结束到接收器。

可能您不知道PrintWriter吞下异常,因此不应该通过网络使用。