java.net.Socket > outputStream > BufferedOutputStream flush() 确认
java.net.Socket > outputStream > BufferedOutputStream flush() confirmation
有没有办法知道 BufferedOutputStream 线程的 flush() 方法何时或是否成功完成?在我的例子中,我使用它通过 java.net.Socket 发送一个简单的字符串。在下面的代码中,flush() 方法 运行 与 BufferedReader.read() 方法并行,套接字输出立即被输入读取阻塞,导致类似于死锁的情况。我想做的是等待输出结束,然后开始读取输入。
Socket sk = new Socket("192.168.0.112", 3000);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write(message.getBytes());
bo.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
if (line.equals("ack")) {
System.out.println("ack");
}
sk.close();
更新
服务器套接字:
ServerSocket ss = new ServerSocket(3000);
System.out.println("server socket open");
while (true) {
Socket sk = ss.accept();
System.out.println("new connection");
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
System.out.println("received line: " + line);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write("ack".getBytes()); bo.flush();
sk.close();
}
更新:
@Global Variable - read 阻塞套接字的原因是它确实在等待 \n。使用
bo.write("ack\n".getBytes());
而不是
bo.write("ack".getBytes());
成功了。
关于最初的问题,有没有办法知道 flush() 方法是否已成功完成,@Stephen C 提供了答案:
there is no way to know that based on the Socket or OutputStream APIs.
The normal way to get that sort of assurance is to have the remote
application send an "reply" in response, and read it in the local
side.
此 "reply" 在代码示例中实现并且有效。
Is there a way of knowing when or whether the flush()
method of a BufferedOutputStream
thread has finished successfully?
这取决于你"finished successfully"的意思。
flush()
方法确保管道中所有未发送的数据已被推送到操作系统网络堆栈。完成后,您可以说 flush()
已成功完成。您知道发生这种情况的方式是 flush()
调用 returns.
另一方面,如果您想要确保数据已经(全部)传送到远程机器,或者远程应用程序已经读取了它(全部)......没有办法知道基于 Socket 或 OutputStream API。获得这种保证的正常方法是让远程应用程序发送一个 "reply" 作为响应,并在本地端读取它。
In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock.
你所说的代码基本上是正确的方法。等待响应的方法就是这样阅读。
如果不行,那么你需要比较客户端和服务器端在做什么:
服务器是否在等待客户端发送更多内容?也许行序列结束?
服务器是否发送响应?
有flush()
回应吗?
客户端和服务器正在执行的操作之间的不匹配可以导致表单或死锁,但解决方案是修复不匹配。等待 flush()
的某种假设性确认不是答案。
更新
确实是不匹配的问题。例如,服务器写 "ack"
但客户端期望 "ack\n"
。在客户端 -> 服务器情况下也会发生同样的情况......除非 message
总是以换行符结尾。
您的代码正在读取 reader.readLine()
。你写的时候写的是\n吗?您可能希望将 \n 附加到您正在编写的字符串中。
我试图重现你的问题。首先,我也 运行 进入某种阻塞状态,直到我意识到,我也在服务器端使用 readLine
。但是我发送的消息没有结尾 \n
。因此,服务器套接字仍在其 InputStream
处等待,而没有通过其 OutputStream
向客户端发送 ACK
。我觉得,@Global Variable
是对的。
有没有办法知道 BufferedOutputStream 线程的 flush() 方法何时或是否成功完成?在我的例子中,我使用它通过 java.net.Socket 发送一个简单的字符串。在下面的代码中,flush() 方法 运行 与 BufferedReader.read() 方法并行,套接字输出立即被输入读取阻塞,导致类似于死锁的情况。我想做的是等待输出结束,然后开始读取输入。
Socket sk = new Socket("192.168.0.112", 3000);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write(message.getBytes());
bo.flush();
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
if (line.equals("ack")) {
System.out.println("ack");
}
sk.close();
更新
服务器套接字:
ServerSocket ss = new ServerSocket(3000);
System.out.println("server socket open");
while (true) {
Socket sk = ss.accept();
System.out.println("new connection");
BufferedReader br = new BufferedReader(new InputStreamReader(sk.getInputStream()));
String line = br.readLine();
System.out.println("received line: " + line);
BufferedOutputStream bo = new BufferedOutputStream(sk.getOutputStream());
bo.write("ack".getBytes()); bo.flush();
sk.close();
}
更新:
@Global Variable - read 阻塞套接字的原因是它确实在等待 \n。使用
bo.write("ack\n".getBytes());
而不是
bo.write("ack".getBytes());
成功了。
关于最初的问题,有没有办法知道 flush() 方法是否已成功完成,@Stephen C 提供了答案:
there is no way to know that based on the Socket or OutputStream APIs. The normal way to get that sort of assurance is to have the remote application send an "reply" in response, and read it in the local side.
此 "reply" 在代码示例中实现并且有效。
Is there a way of knowing when or whether the
flush()
method of aBufferedOutputStream
thread has finished successfully?
这取决于你"finished successfully"的意思。
flush()
方法确保管道中所有未发送的数据已被推送到操作系统网络堆栈。完成后,您可以说 flush()
已成功完成。您知道发生这种情况的方式是 flush()
调用 returns.
另一方面,如果您想要确保数据已经(全部)传送到远程机器,或者远程应用程序已经读取了它(全部)......没有办法知道基于 Socket 或 OutputStream API。获得这种保证的正常方法是让远程应用程序发送一个 "reply" 作为响应,并在本地端读取它。
In the following code, the flush() method is run in parallel with the BufferedReader.read() method and the socket output is immediately blocked by the input read resulting in something that resembles a deadlock.
你所说的代码基本上是正确的方法。等待响应的方法就是这样阅读。
如果不行,那么你需要比较客户端和服务器端在做什么:
服务器是否在等待客户端发送更多内容?也许行序列结束?
服务器是否发送响应?
有
flush()
回应吗?
客户端和服务器正在执行的操作之间的不匹配可以导致表单或死锁,但解决方案是修复不匹配。等待 flush()
的某种假设性确认不是答案。
更新
确实是不匹配的问题。例如,服务器写 "ack"
但客户端期望 "ack\n"
。在客户端 -> 服务器情况下也会发生同样的情况......除非 message
总是以换行符结尾。
您的代码正在读取 reader.readLine()
。你写的时候写的是\n吗?您可能希望将 \n 附加到您正在编写的字符串中。
我试图重现你的问题。首先,我也 运行 进入某种阻塞状态,直到我意识到,我也在服务器端使用 readLine
。但是我发送的消息没有结尾 \n
。因此,服务器套接字仍在其 InputStream
处等待,而没有通过其 OutputStream
向客户端发送 ACK
。我觉得,@Global Variable
是对的。