2010-11-20 3 views
1

Я только что начал использовать java.nio и, вероятно, использовал его неправильно, поэтому у меня возникли небольшие проблемы с ним.Проблемы с неблокирующим выбором с java.nio

Я пытаюсь написать что-то вроде Port Forwarder, который может модифицировать трафик, который проходит через него, используя различные дополнительные модули.

Вот как я это делаю:

  1. ConnectionManager - поток, который имеет собственный селектор, который зарегистрирован в OP_ACCEPT на ServerSocketChannel. Всякий раз, когда он выбирает что угодно - он создает объект подключения ConnectionProcessor, который управляет соединением.

  2. ConnectionProcessor - нить , что открывает SocketChannel с заранее определенной передней точки (где посылать пакеты из недавно подключенного клиента). Затем он открывает свой собственный селектор и регистрирует его для OP_READ клиента SocketChannel и сервер SocketChannel OP_READ.

Затем процессор переходит в бесконечный цикл, выбирая данные из селектора и перенаправляя его соответствующим образом. Чтобы определить, куда отправлять данные, он сравнивает SelectionKey.channel() с clientChannel и serverChannel.

Выбор в ConnectionProcessor производится с таймаутом 5 секунд (выберите (5000)) - для обработки тайм-аутов. При выборе тайм-аута - он пытается прочитать из обоих каналов, чтобы получить исключение или -1 результат.

Теперь вот мои вопросы/проблемы:

  1. ли право использовать key.cancel() после обработки ключа? Большинство примеров, которые я видел в Интернете просто удалите ключ из selectedKeys(). key.cancel() , похоже, намного лучше подходит.
  2. Правильно ли иметь несколько селекторов , которые в основном используют тот же сервер ServerSocketChannel? Или я должен всегда использовать одиночный селектор и передавать выбранные ключи соответствующим менеджерам? То, что я имею в виду, что если 3 клиенты подключаются одновременно, то это то, что будет:

    а) менеджер создает процессор. Процессор открывает клиентский канал. Процессор регистрирует свой собственный селектор на клиентский канал. б) повторение (а) в) повторение (а)

  3. По какой-то причине, после того, как даже один клиент подключается к моей экспедитора - это не будет обрабатывать сообщения быстрее, чем 5000msec тайм-аут. Он начинает выбирать, блокируется в течение 5 секунд, а затем идет на вторую итерацию и получает мне 5-6 сообщений, которые я получил во время предыдущего таймаута. Должен ли я обвинять (1), (2) или какую-то другую причину?
  4. Есть ли какое-либо руководство по поводу того, как все это работает внутри? Я как бы человек, который понимает, как использовать вещи только после того, как я полностью пойму механику внизу. API чтения не помогает, поскольку он написан для людей, которые уже знают правильный способ использования nio.

Спасибо за то, что прочитали весь мой вопрос и заблаговременно за любую помощь.

+0

НИО является утомительным, чтобы получить правильный. Я бы рекомендовал [XNIO] (http://jboss.org/xnio) или [MINA] (http://mina.apache.org/) или insert-NIO-wrapper-library здесь, чтобы сохранить некоторые головные боли и получить более последовательная база. Одной из «простых» проблем с NIO является необходимость пробуждения выбора на готовых к записи данных (что отличается от того, что канал способен писать). Счастливое кодирование. – 2010-11-20 11:26:17

+0

Hm ... Итак, если я что-то помещаю на канал и пытаюсь выбрать из него одновременно, он не будет отправлять какие-либо данные до тех пор, пока выбор не будет завершен? Это страшно, собираюсь проверить XNIO и MINA. Спасибо за совет. – bezmax

+0

Нет, он этого не говорил. Он имеет в виду различные проблемы, возникающие при обработке записей, и существуют различные способы их обработки. Самый простой способ - сделать все записи inline в избранном потоке, но даже у этого есть свои причуды. – EJP

ответ

0
  1. No. Просто удалите ключ из выбранного набора. Обычно это делается через iterator.remove(). Если вы отмените их, то он больше никогда не будет выбран.

  2. Это бессмысленно. Вам не нужен второй селектор или дополнительный поток. Для этого и нужен НИО. Вы можете обрабатывать все это с помощью исходного селектора в исходном потоке.

  3. Возможно, это вызвано странным кодом. Повторите это, как указано выше, и посмотрите, все ли это происходит. Если это так, разместите здесь код.

  4. Вы должны были бы прочитать API Berkeley Sockets или хорошую книгу, такие как Стивенс, Unix Network Programming, или мое ;-)

+0

Спасибо за ответы, собираюсь попробовать их сразу. Что касается (4) - я не имел ввиду оконные сокеты, я имел в виду часть nio. Как работает селектор и т. Д. – bezmax

+0

Кроме того, я не уверен в количестве (2). Дополнительные изменения по пакетам могут занять некоторое время (например, 2-5 секунд), в то время как я хочу поддерживать сразу несколько клиентов. Так каким образом я должен это делать? – bezmax

+0

NIO просто использует select() под капотом, в первом приближении. То, что вы говорите о (2), ничего не меняет. Вы просто выбираете, пока что-то не произойдет, тогда вы справитесь с этим: OP_READ или OP_ACCEPT. – EJP

Смежные вопросы