Java 如何正确使用NIO选择器?

Java 如何正确使用NIO选择器?,java,networking,css-selectors,nio,Java,Networking,Css Selectors,Nio,我在使用选择器时遇到问题 我编写了一些测试代码,尝试创建一个客户端/服务器连接,服务器端有一个选择器来管理通道。问题在于,当选择器选择要读取的通道并处理读取操作时,实际上不会读取任何数据 我把这个问题贴在了上,还没有收到任何答案 服务器: static class Server implements Runnable { Selector sel; @Override public void run() { try { Serve

我在使用选择器时遇到问题

我编写了一些测试代码,尝试创建一个客户端/服务器连接,服务器端有一个选择器来管理通道。问题在于,当选择器选择要读取的通道并处理读取操作时,实际上不会读取任何数据

我把这个问题贴在了上,还没有收到任何答案

服务器:

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();
            }
        }
    }
}
静态类服务器实现可运行{
选择器sel;
@凌驾
公开募捐{
试一试{
ServerSocketChannel服务器=ServerSocketChannel.open();
server.socket().bind(新的InetSocketAddress(5555));
server.configureBlocking(false);
sel=选择器.open();
服务器注册(sel,SelectionKey.OP_ACCEPT);
布尔运行=真;
(跑步时){
int count=sel.select();
如果(sel.isOpen()&&count>0){
Set keyset=sel.selectedKeys();
已同步(键集){
迭代器i=keyset.Iterator();
while(i.hasNext()){
SelectionKey=i.next();
i、 删除();
进程键(key);
}
}
}如果(!sel.isOpen())
运行=错误;
}
}捕获(IOE异常){
e、 printStackTrace();
}
}
私有无效处理密钥(SelectionKey密钥){
if(key.isValid()&&key.isAcceptable()){
试一试{
SocketChannel=((ServerSocketChannel)key.channel()).accept();
chan.configureBlocking(假);
信道寄存器(sel,SelectionKey.OP_READ);
}捕获(IOE异常){
e、 printStackTrace();
}
}
if(key.isValid()&&key.isReadable()){
System.out.println(“读取开始…”);
SocketChannel=(SocketChannel)key.channel();
ByteBuffer buff=ByteBuffer.allocate(1024);
试一试{
而((chan.read(buff))>=0){
buff.flip();
System.out.println(“读取一些”);
buff.clear();
}
chan.close();
System.out.println(“读取完成”);
}捕获(IOE异常){
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();
        }
    }
}
静态类客户端实现可运行{
@凌驾
公开募捐{
试一试{
SocketChannel=SocketChannel.open();
connect(新的InetSocketAddress(“localhost”,5555));
而(!chan.finishConnect());
ByteBuffer buff=ByteBuffer.allocate(1024);

对于(inti=0;i来说,问题在于您的客户机,正如Tom所暗示的,它什么都不写。 下面是发生的情况:

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

这是在javdaoc for flip()中指定的:“将限制设置为当前位置,然后将位置设置为零”。 因此,您至少需要模拟将一些数据放入缓冲区,例如:

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

for(inti=0;i问题出在您的客户机上,正如Tom所暗示的,它什么都不写。
下面是发生的情况:

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

这是在javdaoc for flip()中指定的:“将限制设置为当前位置,然后将位置设置为零”。 因此,您至少需要模拟将一些数据放入缓冲区,例如:

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

for(int i=0;iIt看起来没有写入任何数据。(启动服务器和客户端之间也存在竞争。)我正在尝试写入空字节。它仍然应该写入数据,对吗?在启动客户端代码之前,我尝试使用Thread.sleep(),但没有任何帮助。但您从未填充缓冲区。调用
limit(int)
应该这样做,我想。(免责声明:我已经十年没有真正做过任何合理的NIO编程了。)看起来你没有在写任何数据。(启动服务器和客户端之间也存在竞争。)我正在尝试写空字节。但它仍然应该写数据,对吗?我尝试使用Thread.sleep()在启动客户端代码之前,它没有任何帮助。但是您从未填充缓冲区。我认为,调用
limit(int)
应该可以做到这一点。(免责声明:我实际上已经十年没有做任何合理的NIO编程了。)