[英]Why client can't connect to server in this java nio program?
I'm reading Doug Lea's Scalable I/O in Java , and I followed the Basic Reactor Design example code.我正在阅读 Doug Lea's Scalable I/O in Java ,并且我遵循了Basic Reactor Design示例代码。 But after I started server, the client can't connect to server.但是在我启动服务器后,客户端无法连接到服务器。
Here is the Reactor class:这是反应器类:
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();
}
}
Handler class处理程序类
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();
}
}
}
I start server in idea and then server started is printed in console我在idea中启动服务器,然后在控制台中打印服务器启动
But after I enter telnet localhost 9000
in terminal, client connected: doesn't appear.但是当我在终端中输入telnet localhost 9000
后, client connected:没有出现。
I had to change the Reactor
run method a bit.我不得不稍微改变Reactor
run 方法。 you have to call selector.select()
or selector.selectNow()
:你必须调用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();
}
}
}
that allowed the client to connect.允许客户端连接。
in order to enable an echo service from Handler
I implemented this:为了从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();
}
}
}
register the Handler
instance for reading and then upon a readable selection key the run method of this instance is called to handle the reading.注册用于读取的Handler
实例,然后根据可读的选择键调用该实例的 run 方法来处理读取。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.