2012-02-17 3 views
1

У меня проблема с использованием Selectors.Как правильно использовать селектор NIO?

Я написал несколько тестовых кодов, чтобы попытаться создать соединение Client/Server с селектором на сервере, чтобы управлять каналами. Проблема заключается в том, что, когда селектор выбирает канал для чтения, и операция чтения обрабатывается, данные фактически не считываются.

Я разместил этот вопрос на another forum и еще не получил ответов.

Сервер:

static class Server implements Runnable { 
    Selector sel; 

    @Override 
    public void run() { 
     try { 
      ServerSocketChannel server = ServerSocketChannel.open(); 
      server.socket().bind(new InetSocketAddress(5555)); 
      server.configureBlocking(false); 
      sel = Selector.open(); 
      server.register(sel, SelectionKey.OP_ACCEPT); 

      boolean running = true; 
      while(running) { 
       int count = sel.select(); 
       if(sel.isOpen() && count > 0) { 
        Set<SelectionKey> keyset = sel.selectedKeys(); 
        synchronized(keyset) { 
         Iterator<SelectionKey> i = keyset.iterator(); 
         while(i.hasNext()) { 
          SelectionKey key = i.next(); 
          i.remove(); 
          processKey(key); 
         } 
        } 
       } else if(!sel.isOpen()) 
        running = false; 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void processKey(SelectionKey key) { 

     if(key.isValid() && key.isAcceptable()) { 
      try { 
       SocketChannel chan = ((ServerSocketChannel)key.channel()).accept(); 
       chan.configureBlocking(false); 
       chan.register(sel, SelectionKey.OP_READ); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 

     if(key.isValid() && key.isReadable()) { 
      System.out.println("Read starting..."); 
      SocketChannel chan = (SocketChannel) key.channel(); 
      ByteBuffer buff = ByteBuffer.allocate(1024); 
      try { 
       while((chan.read(buff))>=0) { 
        buff.flip(); 
        System.out.println("read some"); 
        buff.clear(); 
       } 
       chan.close(); 
       System.out.println("Read complete"); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 
} 

Клиент:

static class Client implements Runnable { 
    @Override 
    public void run() { 
     try { 
      SocketChannel chan = SocketChannel.open(); 
      chan.connect(new InetSocketAddress("localhost", 5555)); 
      while(!chan.finishConnect()); 
      ByteBuffer buff = ByteBuffer.allocate(1024); 
      for(int i=0;i<1000;i++) { 
       buff.flip(); 
       chan.write(buff); 
       buff.compact(); 
      } 
      chan.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Вот pastebin полного исходного кода. Любые идеи были оценены.

+1

Не похоже, что вы пишете какие-либо данные. (Существует также гонка между запуском сервера и клиента.) –

+0

Я пытаюсь писать пустые байты. ИТ должен все же писать данные, правда? И я попытался использовать Thread.sleep(), прежде чем инициировать код клиента, и это не помогло. – bgroenks

+1

Но вы никогда не заполняете буфер. Я думаю, что вызов 'limit (int)' должен делать это. (Отказ от ответственности: я на самом деле не делал никаких разумных программ NIO в течение десятилетия). –

ответ

1

Проблема заключается в вашем клиенте, который ничего не пишет, как намекнул Том. вот что происходит:

ByteBuffer buff = ByteBuffer.alloacate(1024); // ==> position=0, limit=1024 

затем:

buff.flip(); // ==> position=0, limit=0 

Это, как указано в javdaoc для флип(): «Лимит устанавливается на текущее положение и положение устанавливается равным нулю ». Так что вам нужно наименее имитировать, что вы положили некоторые данные в буфер, например:

for(int i=0;i<1000;i++) { 
    buff.position(1024); // put 1024 bytes of data in the buffer 
    buff.flip(); 
    ... 
} 

Кроме того, нет никакой гарантии, что chan.write() запишет все 1024 байт на один раз, так что вы могли бы хотите сделать это в петле:

for (int i=0;i<1000;i++) { 
    buf.position(1024); 
    buff.flip(); 
    while (buff.hasRemaining()) { 
    chan.write(buff); 
    buff.compact(); 
    } 
} 
Смежные вопросы