почему метод select сразу возвращает 0, когда я пытаюсь его телнетить? - PullRequest
0 голосов
/ 31 мая 2019

Я не знаком с Java Nio. Я попытался написать небольшое демо, как это:

    ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
    serverSocketChannel.bind(new InetSocketAddress(9999)).configureBlocking(false);
    serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

    for (; ; ) {
        int select = selector.select(2_000);
        if (select == 0) {
            System.out.println("no event");
            continue;
        }
        System.out.println("select = " + select);
   }

Время ожидания установлено на 2 секунды, и программа выводит сообщение «нет события» каждые 2 секунды.

Но когда я попытался связаться с ним по телнету, он начал очень быстро печатать «нет событий». Похоже, что метод select возвращает значение 0 без блокировки.

Почему? Это первый вопрос.

И когда я попытался добавить несколько логик для цикла вроде этого:

for (; ; ) {
            int select = selector.select();
            if (select == 0) {
                System.out.println("no event");
                continue;
            }
            System.out.println("select = " + select);
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            System.out.println("iterator = " + iterator.hasNext());
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                iterator.remove();
            }
        }

Затем я снова запускаю его, метод select возвращает 1.

Почему? Это второй вопрос.

Первый раз задавайте вопросы здесь. Пожалуйста, прости мой плохой английский.

1 Ответ

1 голос
/ 31 мая 2019

Номер, который вы указываете в select (long), не совпадает с Thread.sleep (long). По:

https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Selector.html#select(long)

select является операцией блокировки, но она продолжается, как только она может выбрать канал. Таким образом, когда вы подключены, он будет постоянно зацикливаться и выводить. Длинное значение, которое вы предоставляете, - это указать методу select (long), когда следует прекратить попытки выбора канала, а не приостановить поток независимо. Чтобы гарантировать минимум 2 секунды, вам нужно добавить Thread.sleep (2000) до конца цикла.

Что касается возвращаемого значения, select () возвращает количество обновленных ключей, которое может быть нулевым. Когда вы снова подключаетесь через telnet, вы предоставляете новый ключ, который можно обновить. Если у вас есть только одно соединение, нет необходимости выбирать новый канал для прослушивания. Таким образом, ничто не переключается. Если у вас есть два соединения, имеет смысл, что одно из них будет изменяться каждый раз.

...