java nio在注册写入操作后无法读取

java nio在注册写入操作后无法读取,java,sockets,nio,Java,Sockets,Nio,我在使用JavaNIO进行网络时遇到了一个问题 我在线程中启动服务器,并在选择器中注册读取操作。另一个线程连接到服务器 客户端向服务器写入一个字节 服务器读取数据并向客户端返回一个字节 客户端获得响应并再次向服务器写入一个字节 服务器循环步骤2 但服务器无法成功执行步骤4,因为我无法再从选择器获取任何读取密钥。为什么?我以前注册过,客户已经写了数据 下面是我的代码: package test; import java.io.IOException; import java.net.InetSo

我在使用JavaNIO进行网络时遇到了一个问题

我在线程中启动服务器,并在选择器中注册读取操作。另一个线程连接到服务器

  • 客户端向服务器写入一个字节
  • 服务器读取数据并向客户端返回一个字节
  • 客户端获得响应并再次向服务器写入一个字节
  • 服务器循环步骤2
  • 但服务器无法成功执行步骤4,因为我无法再从选择器获取任何读取密钥。为什么?我以前注册过,客户已经写了数据

    下面是我的代码:

    package test;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.nio.ByteBuffer;
    import java.nio.channels.SelectionKey;
    import java.nio.channels.Selector;
    import java.nio.channels.ServerSocketChannel;
    import java.nio.channels.SocketChannel;
    import java.util.Iterator;
    
    
    public class JavaNIO {
    
        public static void main(String[] args) throws Exception {
            final Selector selector = Selector.open();
            ServerSocketChannel serverChannel = ServerSocketChannel.open();
            serverChannel.configureBlocking(false);
            serverChannel.socket().bind(new InetSocketAddress(5555));
            serverChannel.register(selector, SelectionKey.OP_ACCEPT);
            new Thread() {
                public void run() {
                    while(true) {
                        try {
                            long count = selector.select();
                            if(count == 0) continue;
                            Iterator<SelectionKey> itKey = selector.selectedKeys().iterator();
                            while(itKey.hasNext()) {
                                SelectionKey key = itKey.next();
                                itKey.remove();
                                if(key.isAcceptable()) {
                                    ServerSocketChannel channel = (ServerSocketChannel)key.channel();
                                    SocketChannel socket = channel.accept();
                                    socket.configureBlocking(false);
                                    socket.register(selector, SelectionKey.OP_READ);
    
                                }
                                if(key.isReadable()) {
                                    ByteBuffer buffer=  ByteBuffer.allocate(1);
                                    SocketChannel channel = (SocketChannel)key.channel();
                                    while(true) {
                                        buffer.flip();
                                        int len = channel.read(buffer);
                                        if(len == 0) break;
                                        buffer.clear();
                                    }
                                    channel.read(buffer);
                                    channel.register(selector, SelectionKey.OP_WRITE, null);
                                }
                                if(key.isWritable()) {
                                    SocketChannel channel = (SocketChannel) key.channel();
                                    channel.write(ByteBuffer.wrap("ce".getBytes()));
                                    key.cancel();
                                }
                            }
                        } catch(Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }.start();
            new Thread() {
                public void run() {
                    try {
                        Socket socket = new Socket("localhost", 5555);
                        byte[] reads = new byte[1024];
                        for(int i = 0; i < 1000; i++) {
                            socket.getOutputStream().write(new byte[]{1});
                            socket.getInputStream().read(reads);
                            System.out.println(new String(reads));
                        }
                    } catch (UnknownHostException e) {
                        e.printStackTrace();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    }
    
    封装测试;
    导入java.io.IOException;
    导入java.net.InetSocketAddress;
    导入java.net.Socket;
    导入java.net.UnknownHostException;
    导入java.nio.ByteBuffer;
    导入java.nio.channels.SelectionKey;
    导入java.nio.channels.Selector;
    导入java.nio.channels.ServerSocketChannel;
    导入java.nio.channels.SocketChannel;
    导入java.util.Iterator;
    公共类JavaNIO{
    公共静态void main(字符串[]args)引发异常{
    最终选择器=Selector.open();
    ServerSocketChannel serverChannel=ServerSocketChannel.open();
    serverChannel.configureBlocking(false);
    serverChannel.socket().bind(新的InetSocketAddress(5555));
    serverChannel.register(选择器、SelectionKey.OP_ACCEPT);
    新线程(){
    公开募捐{
    while(true){
    试一试{
    长计数=选择器。选择();
    如果(计数=0)继续;
    迭代器itKey=selector.selectedKeys().Iterator();
    while(itKey.hasNext()){
    SelectionKey=itKey.next();
    itKey.remove();
    if(key.isAcceptable()){
    ServerSocketChannel=(ServerSocketChannel)key.channel();
    SocketChannel socket=channel.accept();
    socket.configureBlocking(false);
    插座.寄存器(选择器,SelectionKey.OP_READ);
    }
    if(key.isReadable()){
    ByteBuffer缓冲区=ByteBuffer.allocate(1);
    SocketChannel=(SocketChannel)key.channel();
    while(true){
    flip();
    int len=通道读取(缓冲区);
    如果(len==0)中断;
    buffer.clear();
    }
    通道读取(缓冲区);
    通道寄存器(选择器,SelectionKey.OP_WRITE,null);
    }
    if(key.isWritable()){
    SocketChannel=(SocketChannel)key.channel();
    channel.write(ByteBuffer.wrap(“ce.getBytes());
    键。取消();
    }
    }
    }捕获(例外e){
    e、 printStackTrace();
    }
    }
    }
    }.start();
    新线程(){
    公开募捐{
    试一试{
    套接字=新套接字(“localhost”,5555);
    字节[]读取=新字节[1024];
    对于(int i=0;i<1000;i++){
    socket.getOutputStream().write(新字节[]{1});
    socket.getInputStream().read(读取);
    System.out.println(新字符串(读取));
    }
    }捕获(未知后异常e){
    e、 printStackTrace();
    }捕获(IOE异常){
    e、 printStackTrace();
    }
    }
    }.start();
    }
    }
    
    您为
    OP\u WRITE
    重新注册了频道,因此它的
    兴趣不再包括
    OP\u READ
    。如果你两者都想要,就相应地改变。”或者把它们放在一起