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