Java NIO. SocketChannel.read method all time return 0. Why?

11,926

Solution 1

Because NIO SocektChannel will not block until the data is available for read. i.e, Non Blocking Channel can return 0 on read() operation.

That is why while using NIO you should be using java.nio.channels.Selector which gives you read notification on channel if the data is available.

On the otherhand, blocking channel will wait till the data is available and return how much data is available. i.e, Blocking channel will never return 0 on read() operation.

You can read more about NIO here:

Solution 2

You have specifically configured

socketChannel.configureBlocking(false);

If you left the default which is blocking then you would never get a length of 0 returned.

Solution 3

While reading the title I was about the say: b/c there is no room in the buffer:

Unlike the answers so far the real culprit is buf.clear().flip(); this effectively sets the buffer like that position=limit=0 - hence no data read - change to buf.clear() and you are good to go.

Have fun w/ the NIO and use debugger before posting a question.

Share:
11,926
user471011
Author by

user471011

Updated on June 25, 2022

Comments

  • user471011
    user471011 almost 2 years

    I try understand how works java NIO. In particular, how works SocketChannel.

    I wrote code below:

    import java.io.*;
    import java.net.*;
    import java.nio.*;
    import java.nio.channels.*;
    
    public class Test {
    
        public static void main(String[] args) throws IOException {
    
            SocketChannel socketChannel = SocketChannel.open();
            socketChannel.configureBlocking(false);
            socketChannel.connect(new InetSocketAddress("google.com", 80));
    
            while (!socketChannel.finishConnect()) {
                // wait, or do something else...
            }
    
            String newData = "Some String...";
    
            ByteBuffer buf = ByteBuffer.allocate(48);
            buf.clear();
            buf.put(newData.getBytes());
    
            buf.flip();
    
            while (buf.hasRemaining()) {
                System.out.println(socketChannel.write(buf));
            }
    
            buf.clear().flip();
    
            int bytesRead;
    
            while ((bytesRead = socketChannel.read(buf)) != -1) {
    
                System.out.println(bytesRead);
    
            }
    
        }
    
    }
    
    1. I try connect to google server.
    2. Send request to the server;
    3. Read answer from the server.

    but, method socketChannel.read(buf) all time return 0 and performs infinitely.

    Where I made mistake??

  • user207421
    user207421 almost 12 years
    Similarly you have initiated a non-blocking connect and then spun until it completes. There's a strong flavor here of trying to write blocking-mode code in non-blocking mode.
  • bestsss
    bestsss almost 12 years
    there is an "endless" loop - so it doesn't matter if the channel is blocking at all. It will eat up CPU but it would read properly if there was any remaining room left in the bytebuffer.
  • user207421
    user207421 almost 12 years
    buffer.clear() or buffer.compact()` are sufficient. buffer.flip() has a different purpose, to put the buffer into a state for getting data out of it.
  • bestsss
    bestsss almost 12 years
    unless noticed, the line is part of the code - which makes the code return '0' into an endless loop. I am perfectly aware how (not) to use flip(), it is effectively limit=position, position=0)
  • user207421
    user207421 over 6 years
    Non-blocking and asynchronous I/O are two different things. Async is still blocking, it just doesn't block you. For example it never returns zero from read.
  • user207421
    user207421 over 6 years
    You have no evidence whatsoever about what he sent. The read could return zero any time, not just because of an incomplete request.
  • TFuto
    TFuto about 4 years
    Thanks @bestsss for this. In some subtle way I run into this "no room in the buffer" issue and was puzzled why I receive 0 byte reads for awhile.