netty(二):NIO——处理可写事件

这篇具有很好参考价值的文章主要介绍了netty(二):NIO——处理可写事件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

处理可写事件

什么情况下需要注册可写事件?

  • 在服务端一次性无法把数据发送完的情况下,需要注册可写事件
    • 服务端一次性是否能够把数据全部发送完成取决于服务端的缓冲区大小,该缓冲区不受程序控制

注册可写事件的步骤

  • 判断ByteBuffer是否仍有剩余,如果有剩余注册可写事件

    ByteBuffer bf = "hello client,welcome";
    SocketChannel sc = (SocketChannel) selectionKey.channel();
    sc.write(bf);
    if(bf.hasRemaining){
        selectionKey.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE);
        selectionKey.attachment(bf);
    }
    
  • 监听可写事件,判断数据是否写完,数据写完需要

    if (key.isWritable()){
        // 监听可写事件
        SocketChannel channel = (SocketChannel) key.channel();
        ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
        channel.write(byteBuffer);
        if (!byteBuffer.hasRemaining()) {
            // 判断数据是否写完
            // 数据写完,解除对buffer的引用
            key.attach(null);
            // 数据写完,不再关注可写事件
            key.interestOps(key.interestOps() - SelectionKey.OP_WRITE);
        }
    }
    

代码示例

  • 客户端

    package com.ysf;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    import java.nio.ByteBuffer;
    import java.nio.channels.SocketChannel;
    import java.nio.charset.Charset;
    
    public class Client {
    
        public static void main(String[] args) throws IOException {
            SocketChannel sc = SocketChannel.open();
            sc.connect(new InetSocketAddress("127.0.0.1",11027));
            sc.write(Charset.defaultCharset().encode("123456\n223456\nhello server\n"));
            while (true){
                ByteBuffer allocate = ByteBuffer.allocate(16);
                sc.read(allocate);
                allocate.flip();
                System.out.println(Charset.defaultCharset().decode(allocate));
            }
        }
    }
    
  • 服务端文章来源地址https://www.toymoban.com/news/detail-673294.html

    package com.ysf;
    
    import java.io.IOException;
    import java.net.InetSocketAddress;
    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.nio.charset.Charset;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.Map;
    
    public class WriterSelectorServer {
    
        public static void handleContent(ByteBuffer byteBuffer){
            byteBuffer.flip();
            for (int i = 0;i < byteBuffer.limit();i++){
                if (byteBuffer.get(i) == '\n'){
                    int length = i + 1 - byteBuffer.position();
                    ByteBuffer allocate = ByteBuffer.allocate(length);
                    for (int j = 0;j<length;j++){
                        allocate.put(byteBuffer.get());
                    }
                    allocate.flip();
                    System.out.println(Charset.defaultCharset().decode(allocate));
                }
            }
            byteBuffer.compact();
        }
    
        public static void main(String[] args) throws IOException {
            Selector selector = Selector.open();
    
            ServerSocketChannel ssc = ServerSocketChannel.open();
            ssc.configureBlocking(false);
            ssc.bind(new InetSocketAddress(11027));
            SelectionKey sscKey = ssc.register(selector, 0, null);
            sscKey.interestOps(SelectionKey.OP_ACCEPT);
    
            while (true){
                selector.select();
                Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()){
                    SelectionKey key = iterator.next();
                    iterator.remove();
                    if (key.isAcceptable()){
                        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();
                        SocketChannel sc = serverSocketChannel.accept();
                        sc.configureBlocking(false);
                        ByteBuffer welcome = Charset.defaultCharset().encode("welcome");
                        sc.write(welcome);
                        Map<String,ByteBuffer> attach = new HashMap<>();
                        ByteBuffer readBuffer = ByteBuffer.allocate(16);
                        attach.put("read",readBuffer);
                        SelectionKey scKey = sc.register(selector, 0, attach);
                        if (welcome.hasRemaining()){
                            attach.put("write",welcome);
                            scKey.interestOps(SelectionKey.OP_READ + SelectionKey.OP_WRITE);
                        }else {
                            scKey.interestOps(SelectionKey.OP_READ);
                        }
                    }else if (key.isReadable()){
                        SocketChannel channel = (SocketChannel) key.channel();
                        Map<String, ByteBuffer> attachment = ((Map<String,ByteBuffer>) key.attachment());
                        ByteBuffer readBuffer = attachment.get("read");
                        int read;
                        try {
                            read = channel.read(readBuffer);
                        } catch (IOException e) {
                            e.printStackTrace();
                            key.cancel();
                            continue;
                        }
                        if (read == -1){
                            key.cancel();
                        }else {
                            handleContent(readBuffer);
                            if (readBuffer.position() == readBuffer.limit()){
                                ByteBuffer newAttachment = ByteBuffer.allocate(readBuffer.capacity() * 2);
                                readBuffer.flip();
                                newAttachment.put(readBuffer);
                                attachment.put("read",newAttachment);
                            }
                        }
                    }else if (key.isWritable()){
                        SocketChannel channel = (SocketChannel) key.channel();
                        Map<String, ByteBuffer> attachment = (Map<String, ByteBuffer>) key.attachment();
                        ByteBuffer byteBuffer = attachment.get("write");
                        channel.write(byteBuffer);
                        if (!byteBuffer.hasRemaining()) {
                            attachment.remove("write");
                            key.interestOps(key.interestOps() - SelectionKey.OP_WRITE);
                        }
                    }
                }
            }
        }
    }
    
    

到了这里,关于netty(二):NIO——处理可写事件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 快速入门Java NIO(Not I/O)的网络通信框架--Netty

    了解netty前需要对nio有一定认识,该笔记基础来自bilinbili黑马,在此基础上自己学习的笔记,添加了一些自己的理解 了解java 非阻塞io编程 1.1 Netty 是什么? Netty 是一个异步(基于多线程)的、基于事件驱动(多路复用的那写事件驱动)的网络应用框架,用于快速开发可维护、高性能的

    2024年01月17日
    浏览(38)
  • 【netty基础四】netty与nio

    阻塞I/O在调用InputStream.read()方法时是 阻塞的,它会一直等到数据到来 (或超时)时才会返回; 同样,在调用ServerSocket.accept()方法时,也会一直 阻塞到有客户端连接 才会返回,每个客户端连接成功后,服务端都会启动一个线程去处理该客户端的请求。 阻塞I/O的通信模型示意

    2024年02月10日
    浏览(77)
  • 聊聊分布式架构06——[NIO入门]简单的Netty NIO示例

    目录 Java NIO和Netty NIO比较 Java NIO: Netty: Netty NIO中的主要模块 Transport(传输层) Buffer(缓冲区) Codec(编解码器) Handler(处理器) EventLoop(事件循环) Bootstrap和Channel(引导和通道) Future和Promise(异步编程) Netty示例 服务端时序图 服务端代码 客户端时序图 客户端代码

    2024年02月07日
    浏览(29)
  • Netty开篇——NIO章下(五)

    SelectionKey 表示 Selector 和网络通道的注册关系,共四种(全是常量): Int OP_ACCEPT:有新的网络连接可以接受,值为 16 (1 4) Int OP_CONNECT: 代表连接已经建立,值为 8 (1 3) Int OP_READ:代表读操作,值为 1 (1 0) Int OP_WRITE: 代表写操作,值为 4  (1 2) 相关方法:   ServerSocket

    2024年01月20日
    浏览(35)
  • Netty开篇——NIO章上(三)

    Java NIO基本介绍 java non-blocking I/O 称为NIO(也叫New IO)。JDK4开始提供,同步非阻塞 相关内容在 java.nio 包及子包下,对java.io 包中的很多类进行改写。 三大核心: Channel(通道),Buffer(缓冲区),Selector(选择器) NIO是 面向缓冲区或者面向块 编程 的 。数据读取到一个它后处理的缓冲区,

    2024年01月16日
    浏览(36)
  • NIO和netty的常用类

    给ServerBootstrap配置两个EventLoopGroup,一个建立连接,一个处理网络io。 EventLoopGroup给EventLoop分配线程。 在 Netty 中,EventLoop 通过不断轮询 Selector 来检测 Channel 上发生的事件,当 Channel 上的事件到达时,EventLoop 会将事件传入 相应的Channel 的成员变量 ChannelPipeline 中,经过所有C

    2024年01月25日
    浏览(39)
  • Netty和传统NIO之间的比较

    Netty回显服务器实现: 上述代码是一个使用Netty实现的回显服务器。让我们逐行解释代码的实现: 首先,我们创建了两个 NioEventLoopGroup ,一个用于接收客户端连接(bossGroup),另一个用于处理客户端连接上的请求(workerGroup)。 然后,我们创建一个 ServerBootstrap 实例,并配置

    2024年01月16日
    浏览(29)
  • Netty Review - NIO空轮询及Netty的解决方案源码分析

    Netty Review - ServerBootstrap源码解析 Netty Review - NioServerSocketChannel源码分析 Netty Review - 服务端channel注册流程源码解析 NIO空轮询(Empty Polling)是指在使用Java NIO 时,当Selector上注册的Channel没有就绪事件时,Selector.select()方法会返回0,但该方法会导致CPU空转,因为它会不断地调用操

    2024年02月21日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包