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

我试着了解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. 从服务器读取答案。

但是,方法socketChannel.read(buf)始终返回0并无限执行。

我弄错了?

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

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

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

您可以在此处阅读有关NIO的更多信息:

您已经专门配置

 socketChannel.configureBlocking(false); 

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

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

与目前的答案不同,真正的罪魁祸首是buf.clear().flip(); 这有效地设置缓冲区,就像position=limit=0 – 因此没有数据读取 – 改为buf.clear() ,你很高兴。

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

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

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

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