Reputation: 4907
My question lies on the following assumptions which I hope are true, because I believe these as I read them while Googling my problems:
So I basically need to anyhow flush the data out of my OutputStream object for my app to work.
If you're interested in details then please see the following two links :
. Weird behavior : sending image from Android phone to Java server (code working)
This issue was resolved by closing the OutputStream. Doing that flushed all the data to the other end of the socket and made my app working further but this fix soon gave rise to problem number 2 - the corresponding socket also gets closed :
. SocketException - 'Socket is closed' even when isConnected() returns true
Upvotes: 6
Views: 23847
Reputation: 7474
public Socket() {
this.impl = factory != null ? factory.createSocketImpl() : new PlainSocketImpl();
this.proxy = null;
}
public class PlainSocketImpl extends SocketImpl {
@Override protected synchronized OutputStream getOutputStream() throws IOException {
checkNotClosed();
return new PlainSocketOutputStream(this);
}
}
private static class PlainSocketOutputStream extends OutputStream {
// doesn't override base class flush();
}
to flush output stream without closing socket you can shutdown output:
protected void shutdownOutput() throws IOException
-- this will close WRITE file descriptor.
instead of using output stream you can write directly to file descriptor or by creating own Socket implementation with OutputStream which will override flush method (for example using a Berkeley socket implementation in c (via native call).
It doesn't need to do anything. Writing to a socket output stream directly isn't buffered by Java, so there is nothing to flush.
-user207421
Upvotes: -1
Reputation: 310913
Closing a Socket's OutputStream closes the socket too
True.
The flush() method of OutputStream does nothing
False. There are overrides. See the Javadoc for FilterOutputStream.flush()
, BufferedOutputStream.flush()
, ObjectOutputStream.flush()
, to name a few. All the streams that can buffer output internally have flush()
methods. All the streams that don't, don't. Specifically, the output stream resulting from Socket.getOutputStream()
is not buffered and does not override flush()
.
So your initial problem is non-existent, so you have no need for the 'solution' that causes problem #2.
Upvotes: 1
Reputation: 718816
The flush() method of OutputStream does nothing.
This is incorrect.
It is true that the base implementation of flush()
provided by the OutputStream
class does nothing. However, your app will be calling the version of that method that is provided by actual stream class that you are using. If the stream class doesn't have direct write semantics, it will override flush()
to do what is required.
In short, if a flush is required (and it is required for a Socket output stream), then calling flush()
will do the right thing. (If some internet source tells you otherwise it is either wrong or you are misinterpreting it.)
FYI, the reason that the base OutputStream
implements flush()
as a no-op is that:
ByteArrayOutputStream
, andflush()
is not a no-op, there is no way to implement the operation at the base class level.They could (in theory) have made designed the stream APIs so that OutputStream
was an abstract class (and flush()
an abstract method) or an interface. However this API was effectively frozen prior to Java 1.0, and at that time there wasn't enough experience with practical Java programming to realize that the API design was suboptimal.
Upvotes: 4
Reputation: 1
I had the same problem. Add "\n" at the end of the stream. flush works but the destinary does not know if the message ended
Upvotes: -1
Reputation: 1
I'll take a stab at it. I was having the same problem. closing the outputstream is the only way i can "flush" the data. but since i still need the outputstream that's not an option. so 1st i send the byte array length, out.writeInt, then the array itself. when all bytes have been read ie buffer.length == in.readInt() i break loop
ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
byte[] fileBytes;
int n;
int length;
try
{
size = in.readInt();
while((n = in.read(buffer)) != -1)
{
dataBuffer.write(buffer, 0, n);
if(dataBuffer.toByteArray().length == length)
{
fileBytes = dataBuffer.toByteArray(); break;
}
}
}
Upvotes: -1
Reputation: 4005
Do you really need to flush? I also had an issue, where listener on c# server couldn't receive data sent from android (I tried to get the data synchronously).
I was sure that this is because on Android side, the following code didn't flush.
OutputStream str = btSocket.getOutputStream();
str.write(data_byte);
// "This implementation does nothing"
str.flush();
It turned out, that if I use asynchronous data retrieval on server's listener - it gets the data, and no flush() on client's side is required!
Upvotes: 0
Reputation: 4958
You can call the flush method of OutputStream instead of close. The concrete classes inheriting from OutputStream will override flush() to do something other than nothing (writing the data to a file or sending it over the network).
Upvotes: 6