1
我遇到了使用選擇器的問題。如何正確使用NIO選擇器?
我寫了一些測試代碼,嘗試在服務器端使用Selector創建客戶端/服務器連接以管理通道。問題是,當Selector選擇要讀取的通道並且處理讀取操作時,實際上沒有數據被讀取。
我發佈了這個問題在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。任何見解都會被讚賞
它看起來不像你正在寫任何數據。 (在啓動服務器和客戶端之間也存在競爭。) – 2012-02-17 17:34:40
我試圖寫空字節。 IT部門仍然應該寫數據?我嘗試在啓動客戶端代碼之前使用Thread.sleep(),但它沒有幫助。 – bgroenks 2012-02-17 23:26:24
但是你永遠不會填滿緩衝區。我想,調用「limit(int)'應該這樣做。 (免責聲明:我實際上沒有做任何明智的NIO編程十年。) – 2012-02-18 01:18:39