Java NIO Socketchannel 关闭输出后才发送数据。为什么是这样?

Java NIO Socketchannel only sends data after shutting down output. Why is this?

好吧,所以我正在尝试编写一个接受 java nio SocketChannel 连接但同时保持打开状态的程序。所以假设客户端发送一条消息,那么服务器应该立即发回相同的消息(简单回声服务器)但是应答过程不起作用,如果客户端发送一条新消息,服务器将不会响应,直到我关闭客户端的套接字通道.但是在我关闭客户端的频道后,所有以前发送的消息都会一次性进入。 (抱歉我的英语不好,这不是我的母语)

写入过程用于Server端和Client端。

编写过程:

                    try {
                        final ByteBuffer byteBuffer = ByteBuffer.wrap(data);
                        while(byteBuffer.hasRemaining()){
                            socketChannel.write(byteBuffer);
                        }
                        byteBuffer.flip();
                    } catch (IOException exception) {
                        throw new BloumException(exception.getMessage());
                    }

阅读过程:

final ByteBuffer byteBuffer = ByteBuffer.allocate(DefaultConnectionCreator.this.getDefaultBufferSize());

                try {
                    while(socketChannel.read(byteBuffer) != -1){    
                        //byteBuffer.clear();
                    }
                } catch (IOException exception) {
                    exception.printStackTrace();
                    throw new BloumException(exception.getMessage());
                }
                return byteBuffer.array();

密钥选择过程(自动关闭Returns false):

private void handleKeys(final ServerSocketChannel serverSocketChannel, Set<SelectionKey> keys, HashMap<SocketChannel, ByteBuilder> sessions) throws Exception{
        final Iterator<SelectionKey> iterator = keys.iterator();
        while(iterator.hasNext()){
            final SelectionKey selectionKey = iterator.next();
            iterator.remove();
            if(selectionKey.isValid()){
                if(selectionKey.isAcceptable()){
                    final ServerSocketChannel serverSocketChannel2 = (ServerSocketChannel)selectionKey.channel();
                    final SocketChannel socketChannel = serverSocketChannel2.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selectionKey.selector(), SelectionKey.OP_READ);
                    sessions.put(socketChannel, new ByteBuilder());

                }else if(selectionKey.isReadable()){
                    final SocketChannel socketChannel = (SocketChannel)selectionKey.channel();
                    final ByteBuffer byteBuffer = ByteBuffer.allocate(Connection.MAX_BUFFER_SIZE);

                    final Integer bytesRead = socketChannel.read(byteBuffer);
                    if(bytesRead!=-1){
                        byte[] data = new byte[bytesRead];
                        System.arraycopy(byteBuffer.array(), 0, data, 0, bytesRead);
                        Boolean autoClose = true;
                        if(ConnectionHost.this.handle(this.getConnectionCreator().createConnection(socketChannel), data)){
                            autoClose=true;
                        }else autoClose=false;


                        if(autoClose){
                            sessions.remove(socketChannel);
                            socketChannel.close();
                        }else{
                            if(!sessions.containsKey(socketChannel))sessions.put(socketChannel, new ByteBuilder());
                        }
                    }
                }else throw new BloumException("The given key is not supported.");
            }else throw new BloumException("The key is not valid anymore.");

        }
    }

您好,您那里有很多错误

  1. 写入前需要翻转缓冲区
  2. 如果读取为 -1,您 必须 关闭频道
  3. 不要创建 1GB 字节的缓冲区,使用的大小是 256、1024、4096、8196 我推荐 4096。
  4. 使用直接缓冲区,直接内存已证明自己对于 I/O 更快,因为它是 未被垃圾收集器中断
  5. 没有布尔值的 if 语句设置布尔值等于语句
  6. 不要有忽略读取字节的 while 循环,如果它是 0 就意味着你 没有任何可读的东西导致你循环直到套接字有 关闭
  7. 我很确定你在那里删除 0 的循环是为了 删除未添加的数据,但您可以这样做 Arrays.copyOfRange(buffer.array(), 0, buffer.position()) 或者如果你 然后翻转缓冲区 Arrays.copyOfRange(buffer.array(), 0, buffer limit())