我试着了解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);
}
}
}
但是,方法socketChannel.read(buf)始终返回0并无限执行。
我犯了错误?
答案 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字节,这意味着没有数据可供读取。