为了账号安全,请及时绑定邮箱和手机立即绑定

Java NIO 套接字通道仅在关闭输出后发送数据。这是为什么呢?

Java NIO 套接字通道仅在关闭输出后发送数据。这是为什么呢?

Helenr 2022-09-22 15:45:57

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


写入过程用于服务器端和客户端。


写作过程:


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();

关键选择过程(自动关闭返回假):


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());

                        

                }

        }

    }


查看完整描述

1 回答

?
繁花如伊

TA贡献1685条经验 获得超12个赞

你好,你有很多错误

  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())


查看完整回答
反对 回复 2022-09-22

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信