2

我尝试了解 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 并无限执行。

我哪里做错了??

4

5 回答 5

6

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

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

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

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

于 2012-07-12T11:47:07.913 回答
5

你已经专门配置了

socketChannel.configureBlocking(false);

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

于 2012-07-12T12:21:51.847 回答
2

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

与迄今为止的答案不同,真正的罪魁祸首是 buf.clear().flip();这样有效地设置缓冲区position=limit=0- 因此没有读取数据 - 更改为buf.clear()并且你很高兴。

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

于 2012-07-12T13:32:54.327 回答
0

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

于 2012-07-12T14:22:06.270 回答
-1

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

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

于 2015-08-08T19:20:33.563 回答