Reputation: 125
is there a way of knowing when or whether the flush() method of a BufferedOutputStream thread has finished successfully? In my case I'm using it for sending a simple string through a java.net.Socket. 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. What I would like to do is wait for the output to end, and then start reading the input.
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();
Update
ServerSocket:
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();
}
Update:
@Global Variable - the reason that read was blocking the socket is that it was waiting for the \n, indeed. Using
bo.write("ack\n".getBytes());
instead of
bo.write("ack".getBytes());
made it work.
Regarding the initial question, is there a way of knowing if flush() method has finished successfully, @Stephen C provided the answer:
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.
This "reply" is implemented in the code sample and it works.
Upvotes: 3
Views: 2672
Reputation: 718708
Is there a way of knowing when or whether the
flush()
method of aBufferedOutputStream
thread has finished successfully?
It depends on what you mean by "finished successfully".
The flush()
method ensures that all unsent data in the pipeline has been pushed as far as the operating system network stack. When that is done, then you could say that flush()
has finished successfully. The way that you know that that has happened is that the flush()
call returns.
On the other hand, if you want some assurance that the data has (all) been delivered to the remote machine, or that the remote application has read it (all) ... 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.
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.
The code that you are talking about is basically the correct approach. The way to wait for the response is to read it like that.
If it is not working, then you need to compare what the client and server side are doing:
Is the server waiting for the client to send something more? Maybe an end of line sequence?
Did the server sends the response?
Did it flush()
the response?
A mismatch between what the client and server are doing can lead to a form or deadlock, but the solution is to fix the mismatch. Waiting for some kind of hypothetical confirmation of the flush()
is not the answer.
UPDATE
The problem is indeed a mismatch. For example, the server writes "ack"
but the client expects "ack\n"
. The same happens in the client -> server case ... unless message
always ends with a newline.
Upvotes: 2
Reputation: 98
I tried to reproduce your problem. First, I ran in to some kind of blocking state too, until I realized, I was using readLine
at Server-side, too. But the message I was sending did not have a concluding \n
. Therefore, the serversocket was still waiting at its InputStream
without sending the client the ACK
through its OutputStream
. I think, @Global Variable
is right.
Upvotes: 0
Reputation: 181
Your code is reading reader.readLine()
. Are your writing \n when writing? You may want to append \n to the string your are writing.
Upvotes: 0