2015-05-03 2 views
1

У меня есть сервер с реализацией NIO с селектором. Реализация довольно проста:Java NIO package sticking

  selector.select(); 
      Set<SelectionKey> keys = selector.selectedKeys(); 
      for (SelectionKey key : keys) { 
       if (! key.isValid()) { 
        continue; 
       } 
       UserConnection connection = users.get(key); 
       if (key.isReadable()) { 
        processReadableKey(key, connection); 
       } else if (key.isWritable()) { 
        processWritableKey(key, connection); 
       } 

Дело в том, когда два пакета (сообщения) прибывает один за другим почти сразу, селектор реагирует и обрабатывает первый, но он не реагирует и отмечает соответствующий ключ как «читаемый» для обработки второго. Когда приходит следующее сообщение, селектор обрабатывает его и после этого обрабатывает этот «потерянный» пакет. Не знаю, как это исправить. Я попытался уменьшить буфер канала, и я попытался разбудить селектор на selector.wakeup(), но это не помогло, потому что проблема связана с распознаванием ключа как «читаемого» сразу после hanling первого сообщения в паре. Любые идеи?

+0

NiO код, как известно, трудно получить точно. это очень сложная апи. если вам не требуется делать это для класса, я бы пошел с фреймворком вроде netty, который скрывает эту сложность под капотом. – jtahlborn

+0

Селектор не пропускает события. Вы уверены, что действительно были действительно два пакета? – EJP

ответ

0

Похоже, вам необходимо удалить ключи выбора из выбранных ключей, установленных перед их использованием. Если вы этого не сделаете, когда вы вызываете selectedKeys(), возвращенный набор по-прежнему будет содержать старые, используемые ключи.

Что-то вдоль линий:

Iterator iter = selector.selectedKeys().iterator(); 
while (iter.hasNext()) { 
    SelectionKey key = (SelectionKey) iter.next(); 
    iter.remove(); // remove here 
    process(key); 
} 
+0

Я удаляю их, к счастью, я вставил не весь код селектора. Проблема решена, она была на клиенте. Клиент также имеет селектор и список сообщений для отправки. После добавления сообщения в список i Invoke selector.wakeup(), но кажется, что если сообщения большие, селектор записывает только первый из них до вызова гнезда. – Luo

+1

@Luo Это неверный анализ. Селектор ничего не пишет. Метод write() - это то, что пишет. Ты думал, что написал что-то, а ты нет. – EJP