Recently I was experimenting with netty. I came across the following problem:
ctx.channel().write(new TextWebSocketFrame("hello")) didnot return hello on the client side, but ctx.channel().writeAndFlush(new TextWebSocketFrame("hello")) did.
What is the difference between two ? ctx is the ChannelHandlerContext.
According to doc
http://netty.io/4.0/api/io/netty/channel/Channel.html
channel.writeAndFlush(msg);
is a shortcut for
channel.write(msg);
channel.flush();
And flush() flushes (writes down) all the pending buffers.
The way I think it works is if you use write and you are sending more data than the buffer can hold it will automatically flush when the buffer is full to make room for more data to be buffered. At the end when there is no more data to push the other data through the buffer you must call flush() to flush whatever is left in the buffer. In your case what you are sending does not excede the buffer size so it sits in the buffer and nothing pushes it through that is why you must call flush() after write to push whatever is left in the buffer through. The writeAndFlush method does this automatically for you I think when it reaches the end it automatically flushes the buffer.
Well, clearly in Netty write() buffers and flush() flushes. Exactly as in a BufferedOutputStream, in fact.
So the question arises: when to flush()? The answer is, at the end of sending a request or a response, unless you're about to close the channel. For example, in a client,merits all the request karts, flush, then read the response. In a server, send all the response parts, and flush.
Related
In Java, one can write a couple of bytes (or however many bytes that is less than the buffer's size) to the socket's output stream and then flush it, in case some bytes need to be sent immediately. In Win32 API, there doesn't seem to be any sort of flush function, so I feel like "flushing" in this case is just padding the rest of the buffer with dummy bytes (probably zeroes) to force the send function to, well, send the data. My question is, how does Java (or even C#, perhaps) implement such a thing under the hood? That is, if I had a Java socket communicating with a Win32 socket somewhere, how would they communicate given that there will be some flushing needed? For example, if the Java socket's buffer were to be flushed (calling flush on the socket's OutputStream), what would I get on the Win32 side (by calling recv)? And the reverse? Would I see some padding behaviour? Would the Win32 side need to know the Java side's buffer size? Something unrelated?
Flushing a Java socket output stream does nothing. Flushing a BufferedOutputStream does something, but only to the application-side buffer. In neither case is there a system call involved other than the send() or write() implied by the flush. You're looking for something that doesn't exist.
so I feel like "flushing" in this case is just padding the rest of the buffer with dummy bytes (probably zeroes) ...
No.
First recall that TCP provides a bidirectional stream of bytes. On one side you write bytes to a socket and the other side can read them from the socket. There is no guarantee whether writing 4 bytes will result in one read call that fetches 4 bytes on the other end. It could also be 2 times 2 bytes. It's no packets or buffers, and therefore "padding the rest of the buffer with dummy bytes" seems like a bad idea, since the other side will eventually receive those dummy bytes (and interpret them for whatever).
Next on to the question:
On the base of all the application there are the OS socket APIs, which provide the write/send calls for the socket. When you write to the OS socket the bytes that are writing are basically only written into the socket send buffer of the OS, from which they will be sent to the remote side at some point of time. This point of time depends on how filled the state of the send buffer is and how things look on the network (TCP windows, network congestion, etc.). However you normally don't have to care about it, the OS will simply send the data eventually and there is no need to flush something. There is one setting on the OS which can be used to influence the sending behavior, which is the nagle algorithm (or TCP_NODELAY) setting. If nagle algorithm is disabled (NODELAY = true) this means the OS will try to send the data immediatly after the write call and doesn't wait for more data from the application in order to send less IP packets. You can use this to reduce latency in case of small packets, but there is no need for it, since the OS will send the data anyway. So it's not a flush in the sense of a required flush.
For the Java side I'm not exactly sure what the flush is doing. It could be that the Java OutputStream has an internal buffer which is only written to the OS socket with the write system call once either a certain treshold of bytes in the buffer is reached or flush is called. Or flush exists purely in order to satisy the OutputStream base class and does nothing extra. You should be safe by using flush on the Java side (or on other platforms where it exists) and doing nothing special in native socket APIs.
In Java, flush() method is used in streams. But I don't understand what are all the purpose of using this method?
fin.flush();
tell me some suggestions.
From the docs of the flush method:
Flushes the output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.
The buffering is mainly done to improve the I/O performance. More on this can be read from this article: Tuning Java I/O Performance.
When you write data to a stream, it is not written immediately, and it is buffered. So use flush() when you need to be sure that all your data from buffer is written.
We need to be sure that all the writes are completed before we close the stream, and that is why flush() is called in file/buffered writer's close().
But if you have a requirement that all your writes be saved anytime before you close the stream, use flush().
When we give any command, the streams of that command are stored in the memory location called buffer(a temporary memory location) in our computer. When all the temporary memory location is full then we use flush(), which flushes all the streams of data and executes them completely and gives a new space to new streams in buffer temporary location.
-Hope you will understand
If the buffer is full, all strings that is buffered on it, they will be saved onto the disk. Buffers is used for avoiding from Big Deals! and overhead.
In BufferedWriter class that is placed in java libs, there is a one line like:
private static int defaultCharBufferSize = 8192;
If you do want to send data before the buffer is full, you do have control. Just Flush It. Calls to writer.flush() say, "send whatever's in the buffer, now!
reference book: https://www.amazon.com/Head-First-Java-Kathy-Sierra/dp/0596009208
pages:453
In addition to other good answers here, this explanation made it very clear for me:
A buffer is a portion in memory that is used to store a stream of data
(characters). These characters sometimes will only get sent to an
output device (e.g. monitor) when the buffer is full or meets a
certain number of characters. This can cause your system to lag if you
just have a few characters to send to an output device. The flush()
method will immediately flush the contents of the buffer to the output
stream.
Source: https://www.youtube.com/watch?v=MjK3dZTc0Lg
Streams are often accessed by threads that periodically empty their content and, for example, display it on the screen, send it to a socket or write it to a file. This is done for performance reasons. Flushing an output stream means that you want to stop, wait for the content of the stream to be completely transferred to its destination, and then resume execution with the stream empty and the content sent.
For performance issue, first data is to be written into Buffer. When buffer get full then data is written to output (File,console etc.). When buffer is partially filled and you want to send it to output(file,console) then you need to call flush() method manually in order to write partially filled buffer to output(file,console).
In the following scenario
ObjectOutputStream output = new ObjectOutputStream(socket.getOutputStream());
output.flush();
// Do stuff with it
Why is it always necessary to flush the buffer after initial creation?
I see this all the time and I don't really understand what has to be flushed. I kind of expect newly created variables to be empty unless otherwise is specified.
Kind of like buying a trash-can and finding a tiny pile of trash inside that came with it.
In over 15 years of writing Java on a professional level I've never once encountered a need to flush a stream before writing to it.
The flush operation would do nothing at all, as there's nothing to flush.
You want to flush the stream before closing it, though the close operation should do that for you it is often considered best practice to do it explicitly (and I have encountered situations where that did make a difference, where apparently the close operation did not actually do a flush first.
Maybe you are confused with that?
When you write data out to a stream, some amount of buffering will occur, and you never know for sure exactly when the last of the data will actually be sent. You might perform many rite operations on a stream before closing it, and invoking the flush()method guarantees that the last of the data you thought you had already written actually gets out to the file. Whenever you're done using a file, either reading it or writing to it, you should invoke the close()method. When you are doing file I/O you're using expensive and limited operating system resources, and so when you're done, invoking close()will free up those resources.
This is needed when using either ObjectInputStream and ObjectOutputStream, because they send a header over the stream before the first write is called. The call to flush() will send that header to the remote side.
According to the spec, the header exists of the following contents:
magic version
If the header doesn't arrive at the moment a ObjectInputStream is build, this call will hang until it received the header bytes.
This means that if the protocol in question is written with ObjectStreams, it should flush after creating a ObjectOutputStream.
It is possible to skip data from an InputStream
in.skip(in.available());
but if you want to do something similar with OutputStream I've found
socket.getOutputStream().flush();
But that's not the same, flush will transmit the buffered data instead of ignoring it.
Is there any possibility of deleting buffered data?
Thanks
EDIT
The situation is a client-server application, when a new command is send (from client)
it (try) to be sure that the answer read will correspond to the last command sent.
Some commands are sent by (human-fired) events, and others are sent by automatic threads.
If a command is on buffer and a new one is send then the answer will be for the first one, causing desynchronization.
Of course a synchronized method plus a flag called "waitingCommand" could be the safer approach but as the communication is not reliable, this approach is slow (depends on timeouts ). That's why I've asked for the skip method.
You can't remove data you could have sent. You can write the data into an in-memory OutputStream like ByteArrayOutputStream and copy only the portions you want.
I'm no sure if it makes sense, but you can try:
class MyBufferedOutputStream extends java.io.BufferedOutputStream {
public MyBufferedOutputStream(OutputStream out) {
super(out);
}
/** throw away everything in a buffer without writing it */
public synchronized void skip() {
count = 0;
}
}
What does it mean to "skip" outputting data?
Once the data is in the buffer, there's no way to get it back or remove it. I suggest checking if you want to skip the data before you write it to the OutputStream. Either that, or have your own secondary buffer that you can modify at will.
This question doesn't make any sense. Throwing away pending requests will just make your application protocol problem worse. What happens to the guy that is waiting for the response to the request that got deleted? What happened to the functionality that that request was supposed to implement? You need to rethink all this from another point of view. If you have a single connection to a server that is executing request/response transactions for this client, the protocol is already sequential. You will have to synchronize on e.g. the socket at the point of writing & flushing the request and reading the response, but you're not losing any performance by this as the processing at the other end is sequentialized anyway. You don't need a 'waitingCommand' flag as well, just synchronization.
Since you are controlling the data written to OutputStream, just don't write pieces that you don't need. OutputStream by contract, does not ensure when data is actually written, so it doesn't make much sense to have skip method.
The best you can do to "ignore" output data, is not to write it at first.
In Java, flush() method is used in streams. But I don't understand what are all the purpose of using this method?
fin.flush();
tell me some suggestions.
From the docs of the flush method:
Flushes the output stream and forces any buffered output bytes to be written out. The general contract of flush is that calling it is an indication that, if any bytes previously written have been buffered by the implementation of the output stream, such bytes should immediately be written to their intended destination.
The buffering is mainly done to improve the I/O performance. More on this can be read from this article: Tuning Java I/O Performance.
When you write data to a stream, it is not written immediately, and it is buffered. So use flush() when you need to be sure that all your data from buffer is written.
We need to be sure that all the writes are completed before we close the stream, and that is why flush() is called in file/buffered writer's close().
But if you have a requirement that all your writes be saved anytime before you close the stream, use flush().
When we give any command, the streams of that command are stored in the memory location called buffer(a temporary memory location) in our computer. When all the temporary memory location is full then we use flush(), which flushes all the streams of data and executes them completely and gives a new space to new streams in buffer temporary location.
-Hope you will understand
If the buffer is full, all strings that is buffered on it, they will be saved onto the disk. Buffers is used for avoiding from Big Deals! and overhead.
In BufferedWriter class that is placed in java libs, there is a one line like:
private static int defaultCharBufferSize = 8192;
If you do want to send data before the buffer is full, you do have control. Just Flush It. Calls to writer.flush() say, "send whatever's in the buffer, now!
reference book: https://www.amazon.com/Head-First-Java-Kathy-Sierra/dp/0596009208
pages:453
In addition to other good answers here, this explanation made it very clear for me:
A buffer is a portion in memory that is used to store a stream of data
(characters). These characters sometimes will only get sent to an
output device (e.g. monitor) when the buffer is full or meets a
certain number of characters. This can cause your system to lag if you
just have a few characters to send to an output device. The flush()
method will immediately flush the contents of the buffer to the output
stream.
Source: https://www.youtube.com/watch?v=MjK3dZTc0Lg
Streams are often accessed by threads that periodically empty their content and, for example, display it on the screen, send it to a socket or write it to a file. This is done for performance reasons. Flushing an output stream means that you want to stop, wait for the content of the stream to be completely transferred to its destination, and then resume execution with the stream empty and the content sent.
For performance issue, first data is to be written into Buffer. When buffer get full then data is written to output (File,console etc.). When buffer is partially filled and you want to send it to output(file,console) then you need to call flush() method manually in order to write partially filled buffer to output(file,console).