Как правильно использовать селекторы NIO? - PullRequest
1 голос
/ 17 февраля 2012

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

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

Я разместил этот вопрос на другом форуме и еще не получиллюбые ответы.

Сервер:

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 Ответ

1 голос
/ 10 марта 2012

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

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

затем:

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

Это так, как указано в javdaoc для flip ():установить на ноль ".Поэтому вам нужно как минимум смоделировать, что вы помещаете некоторые данные в буфер, например:

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();
  }
}
...