gpt4 book ai didi

java - 带有java选择器的无限循环

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:26:38 24 4
gpt4 key购买 nike

我是Java新手,现在对java nio selector有点迷惑,下面是java网络程序3rd一书中的代码,

package org.eclipse.java.socket.samples;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class ChargenServer {
public static int DEFAULT_PORT = 4321;
public static void main(String[] args) {
int port;
try {
port = Integer.parseInt(args[0]);
}
catch (Exception ex) {
port = DEFAULT_PORT;
}
System.out.println("Listening for connections on port " + port);
byte[] rotation = new byte[95 * 2];
for (byte i = ' '; i <= '~'; i++) {
rotation[i - ' '] = i;
rotation[i + 95 - ' '] = i;
}
ServerSocketChannel serverChannel;
Selector selector;
try {
serverChannel = ServerSocketChannel.open();
ServerSocket ss = serverChannel.socket();
InetSocketAddress address = new InetSocketAddress(port);
ss.bind(address);
serverChannel.configureBlocking(false);
selector = Selector.open();
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
}
catch (IOException ex) {
ex.printStackTrace();
return;
}
while (true) {
try {
selector.select();
}
catch (IOException ex) {
ex.printStackTrace();
break;
}
Set<SelectionKey> readyKeys = selector.selectedKeys();
Iterator<SelectionKey> iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
iterator.remove();
try {
if (key.isAcceptable()) {
ServerSocketChannel server = (ServerSocketChannel) key
.channel();
SocketChannel client = server.accept();
System.out
.println("Accepted connection from " + client);
client.configureBlocking(false);
SelectionKey key2 = client.register(selector,
SelectionKey.
OP_WRITE);
ByteBuffer buffer = ByteBuffer.allocate(74);
buffer.put(rotation, 0, 72);
buffer.put((byte) '\r');
buffer.put((byte) '\n');
buffer.flip();
key2.attach(buffer);
}
else if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer buffer = (ByteBuffer) key.attachment();
if (!buffer.hasRemaining()) {
// Refill the buffer with the next line
buffer.rewind();
// Get the old first character
int first = buffer.get();
// Get ready to change the data in the buffer
buffer.rewind();
// Find the new first characters position in
// rotation
int position = first - ' ' + 1;
// copy the data from rotation into the buffer
buffer.put(rotation, position, 72);
// Store a line break at the end of the buffer
buffer.put((byte) '\r');
buffer.put((byte) '\n');
// Prepare the buffer for writing
buffer.flip();
buffer.compact();
}
client.write(buffer);
}
}
catch (IOException ex) {
key.cancel();
try {
key.channel().close();
}
catch (IOException cex) {
}
}
}
}
}
}

服务器很简单,建立一个连接,然后回显一个串口信给客户端,但是当我用

在我的 Ubuntu10.10 上运行它时

Java 版本“1.6.0_20”

OpenJDK 运行时环境 (IcedTea6 1.9.4) (6b20-1.9.4-0ubuntu1)

OpenJDK 服务器虚拟机(build 19.0-b09,混合模式)

我有一个无限循环,我真的不知道为什么,请帮助我!

谢谢大家,但我仍然对选择器感到困惑,现在让事情变得更容易表达我的困惑,看代码:

package org.eclipse.java.socket.selector;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class SocketSelector {
public static void main(String[] args) throws IOException {
// Create selector
Selector selector = null;
selector = Selector.open();
////////////////////////////////////////////////////////////////////////
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(
"localhost", 4321));
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_CONNECT);
/*
* Let's begin select
*/
while (true) {
selector.select();
System.out.println("Hello, selector!");
Set readyKeys = selector.selectedKeys();
Iterator it = readyKeys.iterator();
while (it.hasNext()) {
SelectionKey key = (SelectionKey )it.next();
if (key.isReadable()) {
System.out.println("It's readable!");
}
it.remove();
}
}
}
}

在我的理解中,“selector.select()”等待来自远程服务器的输入事件,然后 it.remove() 删除这个事件,所以选择器开始等待来自远程服务器的新事件,所以客户端可以得到以连续的方式从带有选择器的服务器获取数据,但结果一次又一次地循环,选择器对服务器的数据没有意义,为什么?我的代码有什么问题吗?

最佳答案

三个是代码的多个问题,包括。不关闭选择器。

OP_WRITE 仅当写入整个 Buffer 失败时才需要注册,否则注销。查看 interestedOps()

通常,您需要 OP_READ 才能从该 channel 读取。最后始终检查http://bugs.sun.com在 stackoverflow 之前(这是我跟踪的错误之一)。建议:不要使用相同的选择器来接受/写入。

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4919127

干杯

关于java - 带有java选择器的无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4990474/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com