Let's say we're going to write some bytes to a SocketChannel
within a writable SelectionKey
.
// in a single selection loop
if (selectedKey.isWritable()) {
final var channel = (SocketChannel) selectedKey.channel();
assert !channel.isBlocking(); // checked!
final var buffer = (ByteBuffer) selectedKey.attachment();
assert buffer.hasRemaining(); // checked!
final var w = channel.write(buffer);
assert w >= 0; // ok, no harm
assert w > 0; // really?
}
My question is,
SelectionKey
is writablebuffer
has remaining,Can I technically be assured that the result of the channel.write(buffer)
is always positive?
In a same point of view, is the underlying socket's output buffer always has a free space when the selectedKey.isWritable()
results true
?
P.S. I already check the documentation.
Some types of channels, depending upon their state, may write only some of the bytes or possibly none at all. A socket channel in non-blocking mode, for example, cannot write any more bytes than are free in the socket's output buffer.
Can I technically be assured that the result of the
channel.write(buffer)
is always positive?
TL;DR: as the question is posed, no, there is no such assurance.
The general model of operation for non-blocking channel I/O is that when an I/O operation is requested, as many bytes are transferred as can be done without blocking, up to a maximum of the number requested. That may be 0 bytes. Under the conditions you describe, that would normally be a positive number of bytes, but
If there is another thread that could attempt to write to the channel then between when the channel is selected for writability and when the thread you are focusing on attempts to write, the other thread could transfer enough bytes to the channel that it is no longer writable without blocking. In that case, the write()
you are focusing on could return 0.
There are various conditions in which the write()
could throw an exception instead of returning anything at all.
Even if neither of the above applies, Java simply does not provide a guarantee that you will see a positive number of bytes written in such a case, only that the attempt will not block. The write is highly likely to return a positive result if neither of the above points applies, and there may be platforms where you can safely rely on that, but Java does not assure it. Robust code should be prepared for the possibility that the write()
returns 0.
In a same point of view, is the underlying socket's output buffer always has a free space when the
selectedKey.isWritable()
resultstrue
?
A channel's selection key indicating that the channel is writable means that at least one byte can be transferred to it without blocking. There is only indirect attestation to there being an underlying output buffer at all, though in practice, that is indeed how all socket implementations I know work. Supposing that there is indeed an output buffer, yes, the channel being writable means there is at least one byte of space available in that buffer.