Java NIO。 SocketChannel.read方法一直返回0.为什么?

时间:2012-07-12 11:45:22

标签: java sockets nio socketchannel

我试着了解java NIO是如何工作的。特别是SocketChannel如何工作。

我在下面写了代码:

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. 我尝试连接到谷歌服务器。
  2. 向服务器发送请求;
  3. 从服务器上阅读答案。
  4. 但是,方法socketChannel.read(buf)始终返回0并无限执行。

    我犯了错误?

5 个答案:

答案 0 :(得分:6)

因为NIO SocektChannel在数据可供读取之前不会阻止。即,非阻塞频道可以return 0 on read() operation

这就是为什么在使用NIO时你应该使用java.nio.channels.Selector,如果数据可用,它会在通道上提供阅读通知。

另一方面,阻塞通道将等待数据可用并返回可用数据量。即,阻止频道永远不会return 0 on read() operation

您可以在此处详细了解NIO:

答案 1 :(得分:4)

您已经专门配置了

socketChannel.configureBlocking(false);

如果您保留阻止的默认值,那么您将永远不会返回0的长度。

答案 2 :(得分:1)

在阅读标题时,我是在说:b / c缓冲区中没有空间:

与目前的答案不同,真正的罪魁祸首是buf.clear().flip();这有效地设置了缓冲区,因为position=limit=0 - 因此没有数据读取 - 更改为buf.clear(),你就可以了。< / p>

在发布问题之前与NIO玩得开心并使用调试器。

答案 3 :(得分:0)

如果你真的想使用非阻塞I / O,那么要么使用选择器,要么使用Java 7中的nio2(AsynchronousSocketChannel等)。使用选择器很棘手,更好地找到准备好的工作示例。使用nio2相对容易。

答案 4 :(得分:-1)

技术说明是您没有向Google网络服务器发送完整的HTTP请求,因此在收到完整的请求之前,它不会向您发送回复。

这解释了为什么要读取0字节,这意味着没有数据可供读取。