java 爪哇蔚来。SocketChannel.read 方法一直返回 0。为什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11451118/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 05:10:22  来源:igfitidea点击:

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

javasocketsniosocketchannel

提问by user471011

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

我尝试了解 java NIO 的工作原理。特别是 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.
  1. 我尝试连接到谷歌服务器。
  2. 向服务器发送请求;
  3. 从服务器读取答案。

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

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

Where I made mistake??

我哪里出错了??

回答by Ramesh PVK

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

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

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

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

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.

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

You can read more about NIO here:

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

回答by Peter Lawrey

You have specifically configured

你专门配置了

socketChannel.configureBlocking(false);

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

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

回答by bestsss

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

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

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.

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

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

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

回答by Alexei Kaigorodov

If you really want to use non-blocking I/O, then either use selector, or use nio2 (AsynchronousSocketChannel et al.) from Java 7. Using selector is tricky, better find ready working examples. Using nio2 is relatively easy.

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

回答by user1187372

The technical explanation is that you didn't send a complete HTTP request to the google webserver, therefore it won't send you a reply until it receives a complete request.

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

This explains why you are reading 0 bytes which means that no data is available for reading.

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