gpt4 book ai didi

写入 channel 后,Java Selector 在无限循环中返回带有 OP_READ 的 SelectionKey,没有数据

转载 作者:搜寻专家 更新时间:2023-11-01 02:15:01 26 4
gpt4 key购买 nike

我的代码有问题:我用 Selector 编写了简单的 SocketChannel 客户端,启动后它成功地从服务器读取消息(服务器发送事件)。但是在写入套接字后(参见 main 方法)选择器开始在无限循环中返回可读套接字,handleKey 返回读取的 -1 字节,因此选择器始终返回 OP_READ SelectionKey 而没有数据可供读取。对不起我的英语不好。

谢谢。

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
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;

public class SelectorTest
{

public SelectorTest() throws IOException {
selector = Selector.open();
}

private void runSelector() {

new Thread(new Runnable() {

public void run()
{

alive = true;
try {
while(alive) {
System.out.println("Selector started...");

selector.select();

Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator();

while(keyIter.hasNext()) {

SelectionKey key = keyIter.next();

keyIter.remove();

handleKey(key);
}
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
}).start();
}

private void handleKey(SelectionKey key) throws IOException {

SocketChannel chan = (SocketChannel) key.channel();
System.out.println("Processing selected...");

if(key.isConnectable()) {
System.out.println("Connecting ...");
if(chan.finishConnect()) {
key.interestOps(SelectionKey.OP_READ);
} else {
key.channel();
}
} else if(key.isReadable()) {
System.out.println("Processing reading...");

ByteBuffer buf = ByteBuffer.allocate(1024);
int readedBytes = chan.read(buf);
System.out.println("Readed: " + readedBytes);
buf.flip();

for(byte b : buf.array()) {
System.out.print((char) b);
}
} else if(key.isWritable()) {
System.out.println("Finishing writing...");

key.interestOps(SelectionKey.OP_READ);
}
}

public static void main(String[] args) throws IOException {

SocketChannel channel = SocketChannel.open();
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("t1.sis.lan", 6001));

SelectorTest ds = new SelectorTest();
ds.runSelector();

channel.register(ds.selector, SelectionKey.OP_CONNECT);

BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

for(;;) {

String line = in.readLine();
if(line==null) break;

if(line.toLowerCase().equals("bye")) break;

if (line.toLowerCase().equals("write")) {
String command = "GET_STREAMS\r\n\0";

ByteBuffer buf = ByteBuffer.allocate(1024);
buf.put(command.getBytes());
buf.flip();

channel.write(buf);
}

System.out.println("echo: "+line); // is it alive check
}

ds.alive = false;
ds.selector.wakeup();
channel.close();
}

private Selector selector;
private boolean alive;

}

最佳答案

read() 在 EOS 处返回 -1,您完全忽略了这一点。当您获得 EOS 时,您必须关闭 channel 或至少注销对 OP_READ 的兴趣。否则,当你阅读时,你将永远得到另一个 OP_READ 和另一个 -1 。与您上面的评论相反,read() 在空读取时返回 。你可以忽略它,事实上,如果你只在 isReadable() 时读取,你甚至看不到它,除非你在循环中读取,但你不能忽略 EOS。

关于写入 channel 后,Java Selector 在无限循环中返回带有 OP_READ 的 SelectionKey,没有数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7937908/

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