gpt4 book ai didi

java - 为什么在这个java nio程序中客户端无法连接到服务器?

转载 作者:行者123 更新时间:2023-12-02 08:52:05 27 4
gpt4 key购买 nike

我正在阅读 Doug Lea 的 Scalable I/O in Java ,我遵循了基本 react 器设计示例代码。但是启动服务器后,客户端无法连接到服务器。

这是 Reactor 类:

class Reactor implements Runnable {

private static final Logger logger = LogManager.getLogger();

final Selector selector;
final ServerSocketChannel serverSocket;

public Reactor(int port) throws IOException {
selector = Selector.open();
serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress(port));
serverSocket.configureBlocking(false);
SelectionKey sk = serverSocket.register(selector, SelectionKey.OP_ACCEPT);
sk.attach(new Acceptor());
logger.info("server started.");
}

@Override
public void run() {
while (!Thread.interrupted()) {
for (final Iterator<SelectionKey> it = selector.selectedKeys().iterator(); it.hasNext(); it.remove()) {
dispatch(it.next());
}
}
}

private void dispatch(SelectionKey key) {
Runnable r = (Runnable) key.attachment();
if (r != null) {
r.run();
}
}

private final class Acceptor implements Runnable {
@Override
public void run() {
try {
SocketChannel c = serverSocket.accept();
if (c != null) {
new Handler(selector, c);
}
} catch (IOException ex) {
ex.getMessage();
}
}
}

public static void main(String[] args) throws IOException {
new Reactor(9000).run();
}
}

处理程序类

final class Handler implements Runnable {
private static final Logger logger = LogManager.getLogger();

final SocketChannel c;
final SelectionKey key;
ByteBuffer buffer = ByteBuffer.allocate(1024);

public Handler(Selector sel, SocketChannel c) throws IOException {
this.c = c;
c.configureBlocking(false);
key = c.register(sel, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
logger.info("client connected: " + c);
}

void read() throws IOException {
if (!buffer.hasRemaining()) {
return;
}
c.read(buffer);
}

void process() {/* */}

void write() throws IOException {
buffer.flip();
c.write(buffer);
c.close();
}

@Override
public void run() {
try {
read();
process();
write();
} catch (IOException ex) {
ex.getMessage();
}
}
}

我在idea中启动服务器,然后在控制台中打印服务器已启动
但是当我在终端中输入telnet localhost 9000后,客户端已连接:不会出现。

最佳答案

我必须稍微更改一下 Reactor 运行方法。您必须调用 selector.select()selector.selectNow():

    @Override
public void run() {
while (!Thread.interrupted()) {
try {
int ready = selector.selectNow();
if (ready == 0){
continue;
}

Set<SelectionKey> selected = selector.selectedKeys();
Iterator<SelectionKey> it = selected.iterator();
while (it.hasNext()) {
SelectionKey key = it.next();
if(key.isAcceptable() || key.isReadable()) {
dispatch(key);
}
}
selected.clear();
} catch (IOException e) {
e.printStackTrace();
}
}
}

允许客户端连接。

为了从Handler启用回显服务,我实现了这个:

final class Handler implements Runnable {
private static final Logger logger = LogManager.getLogger();
final SocketChannel c;
final SelectionKey key;
ByteBuffer buffer = ByteBuffer.allocate(1024);

public Handler(Selector selector, SocketChannel c) throws IOException {
this.c = c;
c.configureBlocking(false);
logger.info("client connected: " + c);

key = c.register(selector, 0);
key.attach(this);
key.interestOps(SelectionKey.OP_READ);
selector.wakeup();
}


@Override
public void run() {
try {
SocketChannel client = (SocketChannel) key.channel();
client.read(buffer);
if (new String(buffer.array()).trim().equals("close")) {
client.close();
System.out.println("close connection");
}

buffer.flip();
client.write(buffer);
buffer.clear();
} catch (IOException ex) {
ex.getMessage();
}
}
}

注册Handler实例进行读取,然后根据可读的选择键调用该实例的run方法来处理读取。

关于java - 为什么在这个java nio程序中客户端无法连接到服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60708854/

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