【问题标题】:The simplest NIO-server example最简单的 NIO-server 示例
【发布时间】:2017-08-11 09:23:21
【问题描述】:

我正在尝试运行只接受连接的最简单的 NIO 服务器。

public static void main(String[] args) throws IOException{
    Selector selector = Selector.open();
    ServerSocketChannel serverChannel = ServerSocketChannel.open();
    serverChannel.configureBlocking(false);
    serverChannel.socket().bind(new InetSocketAddress("localhost", 1456));
    serverChannel.register(selector, SelectionKey.OP_ACCEPT);
    while (true) {
        try {
            selector.select();
            Iterator<SelectionKey> keys = selector.selectedKeys().iterator();
            while (keys.hasNext()) {
                SelectionKey key = keys.next();
                if (key.isAcceptable())
                    accept(key, selector);
            }
        } catch (IOException e) {
            System.err.println("I/O exception occurred");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

private static void accept(SelectionKey key, Selector selector) throws IOException{
    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
    SocketChannel channel = serverChannel.accept();
    channel.configureBlocking(false);         //<------- NPE Here
    channel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
    channel.setOption(StandardSocketOptions.TCP_NODELAY, true);
    channel.register(selector, SelectionKey.OP_READ);
}

还有最简单的 I/O 客户端:

 public static void main(String[] ars) throws IOException{
        Socket s = new Socket("localhost", 1456);
        OutputStream ous = s.getOutputStream();
        InputStream is = s.getInputStream();
        while (true) {
            ous.write(new byte[]{1, 2, 3, 3, 4, 5, 7, 1, 2, 4, 5, 6, 7, 8});
            is.read();
        }
    }

当我运行这两个进程时,我得到了一堆NullPointterExceeptions。

当客户端第一次连接时,没关系。我们检索密钥,获取通道并接受传入连接。

但问题是我不清楚的原因是我不断检索可接受的密钥并尝试接受更多。 SocketChannel channel = serverChannel.accept(); 为空,我得到 NPE

但是为什么我总是收到被接受的密钥通知?我做错了什么?

【问题讨论】:

    标签: java nio


    【解决方案1】:

    您需要在处理完每个SelectionKey 从选定的集合中删除它。否则,您将再次收到相同的事件,即使它还没有真正准备好:例如,accept() 将返回 null。

    您需要查看教程。没有好处,只是弥补。请参阅 Oracle NIO 教程。

    【讨论】:

    • 读操作也是这样吗?我的意思是当我从一个频道中读到一些东西时......我需要从选定的集合中删除它吗?还是直接取消?
    • 所有操作都是如此,任何教程都会告诉你。很少需要取消SelectionKey
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-12
    • 1970-01-01
    • 2017-09-27
    • 2016-12-17
    • 2019-05-24
    相关资源
    最近更新 更多