通过SocketChannel读取(写入)的正确方法

问题描述 投票:1回答:1

我的问题比以下情况更通用,尽管涵盖了所需的一切。它适用于Java和套接字编程的正确做法。

场景:

  • 一台具有许多客户端的服务器。 非阻塞I / O
  • 的用法
  • 该服务器是另一台服务器的客户端。 阻塞I / O
  • 的用法
  • 每种情况两种:在一种情况下,所有数据都适合于分配的字节缓冲区内,在第二种情况下,它们均不适合(仅一次迭代,不影响程序的寿命)。>>
  • 我发现的非阻塞I / O的所有示例都是这样的:

InetAddress host = InetAddress.getByName("localhost");
Selector selector = Selector.open();
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.bind(new InetSocketAddress(host, 1234));
serverSocketChannel.register(selector, SelectionKey. OP_ACCEPT);
while (true) {
   if (selector.select() <= 0)
       continue;
   Set<SelectionKey> selectedKeys = selector.selectedKeys();
   Iterator<SelectionKey> iterator = selectedKeys.iterator();
   while (iterator.hasNext()) {
       key = (SelectionKey) iterator.next();
       iterator.remove();
       if (key.isAcceptable()) {
           SocketChannel socketChannel = serverSocketChannel.accept();
           socketChannel.configureBlocking(false);
           socketChannel.register(selector, SelectionKey.OP_READ);
           // Do something or do nothing
       }
       if (key.isReadable()) {
           SocketChannel socketChannel = (SocketChannel) key.channel();
           ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
           socketChannel.read(buffer);
           // Something something dark side
           if (result.length() <= 0) {
               sc.close();
               // Something else
           }
        }
    }

read是否在缓冲区足够大的情况下从该特定客户端和该特定请求读取所有传入的数据,还是我需要将其放入while循环内?如果缓冲区不够大?

[write的情况下,我是否也只做socketChannel.write(buffer),并且我很好(至少从程序的角度来看)?

doc here未指定所有传入数据都适合缓冲区的情况。当我有一个阻塞的I / O时,这也使它有些混乱:

但是,如果通道处于阻塞模式并且缓冲区中至少有一个字节剩余,那么此方法将阻塞直到读取至少一个字节。

这是否意味着在这里(阻塞I / O)我需要以任何一种方式通过read循环while(我发现的大多数示例都这样做)? write操作怎么样?

因此,总而言之,我的问题是,从中间服务器(客户端到第二台服务器)的角度来看,在我的场景中读写数据的正确方法是什么?

我的问题比以下情况更通用,尽管涵盖了所需的一切。它适用于Java和套接字编程的正确做法。场景:一台服务器上有很多客户端。...

java loops nonblocking writing socketchannel
1个回答
0
投票

如果您没有调用configureBlocking(false),则可以,请使用循环来填充缓冲区。

© www.soinside.com 2019 - 2024. All rights reserved.