Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何测试非阻塞通道的SocketChannel.read()是否已完成?_Java_Sockets_Nio_Nonblocking_Socketchannel - Fatal编程技术网

Java 如何测试非阻塞通道的SocketChannel.read()是否已完成?

Java 如何测试非阻塞通道的SocketChannel.read()是否已完成?,java,sockets,nio,nonblocking,socketchannel,Java,Sockets,Nio,Nonblocking,Socketchannel,我正在使用一个函数从非阻塞SocketChannel(accept()的套接字)和阻塞SocketChannel(客户端)读取字节。我正在使用选择器实现一个服务器来处理多个客户端,并且我正在使用环回地址来仅使用我的笔记本电脑。这是我写的 while((r = socketChannel.read(ackBuf)) != -1) { System.out.println(name3d+" r: "+r); } 我希望当到达频道内容的末尾时,read()会返回-1,但不是成

我正在使用一个函数从非阻塞SocketChannel(accept()的套接字)和阻塞SocketChannel(客户端)读取字节。我正在使用选择器实现一个服务器来处理多个客户端,并且我正在使用环回地址来仅使用我的笔记本电脑。这是我写的

while((r = socketChannel.read(ackBuf)) != -1) {
        System.out.println(name3d+" r: "+r);
    }
我希望当到达频道内容的末尾时,read()会返回-1,但不是成功的结果。 read(),在非阻塞配置中,如果此时还没有准备好读取的内容,则返回0,但如果我将代码更改为

while((r = socketChannel.read(ackBuf)) > 0) {
        System.out.println(name3d+" r: "+r);
    }
如果稍后有东西准备好,我也不会什么都不看。 如何区分我得到0是因为未准备好还是因为它已结束? 在下面的代码片段中,我可以在睡眠后再次测试读取,但我确信这不是我想要的可靠方法

int times = 0;
while((r = socketChannel.read(ackBuf)) != -1 && times<2) {
    if (r == 0)
        try {
            Thread.sleep(500);
            times++;
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    System.out.println(name3d+" r: "+r);
}
int次=0;
while((r=socketChannel.read(ackBuf))!=-1&ד如果我得到0是因为没有准备好还是因为它结束了?”你是指消息还是整个通信

对于消息,您应该使用通信协议(如json或http)进行通信,我认为您应该得到一个SocketException…如果您使用阻塞,另一端的人关闭了连接,您会得到…(我已经写信给很多人,告诉他们SocketException是您的朋友)

---编辑---

查看通道的文档,如果/当通道关闭时,您应该会得到某种IOException(SocketException是IOException的子类)。如果“我得到0是因为未准备好还是因为它已结束?”您是指消息还是通信的全部

对于消息,您应该使用通信协议(如json或http)进行通信,我认为您应该得到一个SocketException…如果您使用阻塞,另一端的人关闭了连接,您会得到…(我已经写信给很多人,告诉他们SocketException是您的朋友)

---编辑---


查看通道的文档,如果/当通道关闭时,使用的非阻塞SocketChannel有点不同,那么您应该会得到某种类型的IOException(SocketException是IOException的子类)

  • 首先等待选择键告诉您有数据,然后
  • 然后从通道读取数据
  • 参见本规范草案:

      Selector selector = Selector.open();
      SocketChannel sc = SocketChannel.open();
      sc.configureBlocking(false);
      sc.connect(addr);
      sc.register(selector, SelectionKey.OP_READ);
      while (true) {
        // select() can block!
        if (selector.select() == 0) {
          continue;
        }
        Iterator iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
         SelectionKey key = (SelectionKey) iterator.next();
         iterator.remove();
         if (key.isReadable()) {
           SocketChannel sc = (SocketChannel) key.channel();
           ByteBuffer bb = ByteBuffer.allocate(1024);
           sc.read(bb);
           System.out.println("Message received!");
         }
    }
    

    使用的非阻塞SocketChannel有点不同

  • 首先等待选择键告诉您有数据,然后
  • 然后从通道读取数据
  • 参见本规范草案:

      Selector selector = Selector.open();
      SocketChannel sc = SocketChannel.open();
      sc.configureBlocking(false);
      sc.connect(addr);
      sc.register(selector, SelectionKey.OP_READ);
      while (true) {
        // select() can block!
        if (selector.select() == 0) {
          continue;
        }
        Iterator iterator = selector.selectedKeys().iterator();
        while (iterator.hasNext()) {
         SelectionKey key = (SelectionKey) iterator.next();
         iterator.remove();
         if (key.isReadable()) {
           SocketChannel sc = (SocketChannel) key.channel();
           ByteBuffer bb = ByteBuffer.allocate(1024);
           sc.read(bb);
           System.out.println("Message received!");
         }
    }
    

    因此,如果选择了socketChannel的键,我将永远不会得到0!这解释了所有问题。谢谢:)以防御方式发言,不一定。但大多数情况下,您都有机会获得超过0的分数。:-)因此,如果选择了socketChannel的键,我将永远不会得到0!这就解释了一切。谢谢:)用防御的语气说,不一定。但大多数情况下,您都有机会获得超过0的分数。:-)我在谈论这个消息。我使用自己的协议,在客户端设置与服务器的TCP通信后,客户端通过socketchannel发送一些字节,第一个字节用于标识特定请求,以便服务器了解客户端请求的类型。以类似的方式,服务器向clientI发送字节,我正在谈论该消息。我使用自己的协议,在客户端设置与服务器的TCP通信后,客户端通过socketchannel发送一些字节,第一个字节用于标识特定请求,以便服务器了解客户端请求的类型。服务器以类似的方式向客户端发送字节