【发布时间】:2020-02-26 08:19:32
【问题描述】:
我的问题比以下情况更笼统,尽管这涵盖了所需的一切。 是针对Java和socket编程的正确做法。
场景:
- 一台服务器有许多客户端。 非阻塞 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) 并且我很高兴(至少从程序的角度来看)?
文档here 没有指定所有传入数据都适合缓冲区的情况。当我有阻塞 I/O 时,它也会让人有点困惑:
但是,可以保证,如果通道处于阻塞模式并且缓冲区中至少有一个字节剩余,则此方法将阻塞,直到读取至少一个字节。
这是否意味着在这里(阻塞 I/O)我需要通过while 循环来read(我发现的大多数示例都是这样做的)? write 操作呢?
所以,总而言之,我的问题是,从中间服务器(客户端到第二台服务器)的角度来看,在我的场景中读取和写入数据的正确方法是什么?
【问题讨论】:
标签: java loops nonblocking writing socketchannel