我试图了解如何使用一个选择器和多个通道编写最简单的应用程序。
经过不可思议的努力,我能够编写以下代码:
服务器:
private static byte[] data = new byte[255];
public static void main(String[] args) throws IOException {
for (int i = 0; i < data.length; i++)
data[i] = (byte) i;
ServerSocketChannel server = ServerSocketChannel.open();
server.configureBlocking(false);
server.socket().bind(new InetSocketAddress(9000));
Selector selector = Selector.open();
server.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
selector.select();
Set readyKeys = selector.selectedKeys();
Iterator iterator = readyKeys.iterator();
while (iterator.hasNext()) {
SelectionKey key = (SelectionKey) iterator.next();
iterator.remove();
if (key.isAcceptable()) {
SocketChannel client = server.accept();
System.out.println("Accepted connection from " + client);
client.configureBlocking(false);
ByteBuffer source = ByteBuffer.wrap(data);
SelectionKey key2 = client.register(selector, SelectionKey.OP_WRITE);
key2.attach(source);
} else if (key.isWritable()) {
SocketChannel client = (SocketChannel) key.channel();
ByteBuffer output = (ByteBuffer) key.attachment();
if (!output.hasRemaining()) {
output.rewind();
}
client.write(output);
}
key.channel().close();
}
}
}
客户端(发送者):
public static void main(String[] argv) throws Exception {
SocketChannel sChannel = SocketChannel.open();
sChannel.configureBlocking(false);
sChannel.connect(new InetSocketAddress("localhost", 9000));
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
buf.put((byte) 0xFF);
buf.flip();
int numBytesWritten = sChannel.write(buf);
}
我的步骤:
- 运行服务器
- 运行客户端
醇>
在服务器控制台中执行此步骤之后,我会看到以下内容:
Accepted connection from java.nio.channels.SocketChannel[connected local=/127.0.0.1:9000 remote=/127.0.0.1:49184]
在客户端控制台中,我看到以下内容:
Exception in thread "main" java.nio.channels.NotYetConnectedException
at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(SocketChannelImpl.java:269)
at sun.nio.ch.SocketChannelImpl.write(SocketChannelImpl.java:474)
at io.nio.SocketSender.main(SocketSender.java:25)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)
请帮助理解堆栈跟踪的原因。
答案 0 :(得分:0)
信息很清楚。我会以阻塞模式进行客户端连接:然后它完成或失败。否则你必须使用Selector,选择OP_CONNECT,使用finishConnect(),测试它的返回值等。实际上我会通过客户端使用阻塞模式,我可能根本不会使用NIO。