簡體   English   中英

如何正確使用NIO選擇器?

[英]How to use NIO Selectors correctly?

我在使用選擇器時遇到問題。

我編寫了一些測試代碼,以嘗試使用服務器端的選擇器創建客戶端/服務器連接以管理通道。 問題是當選擇器選擇要讀取的通道並處理了讀取操作時,實際上沒有數據被讀取。

我在另一個論壇上發布了此問題,但尚未收到任何答案。

服務器:

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 任何見解表示贊賞。

問題出在您的客戶身上,它沒有寫任何東西,湯姆暗示。 這是發生了什么:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM