NIO有关知识(二)

前景回顾

NIO有关知识点(一)_运气不好努力来凑-CSDN博客NIO?selector?epoll?不明白的看过来https://blog.csdn.net/wai_58934/article/details/122898928?spm=1001.2014.3001.5501接着昨天写的继续。

重要的是调用底层的三个函数,分别是

epoll_create:生成一个epoll专用的文件描述符。它其实是在内核申请一空间,用来存放你想关注的socket fd上是否发生以及发生了什么事件

epoll_ctl:epoll的事件注册函数,用于控制某个epoll文件描述符上的事件,可以注册事件,修改事件,删除事件。

epoll_wait:等待事件的产生,该函数返回需要处理的事件数目.等待注册在epfd上的socket fd的事件的发生,如果发生则将发生的sokct fd和事件类型放入到events数组中。并且将注册在epfd上的socket fd的事件类型给清空,所以如果下一个循环你还要关注这个socket fd的话,则需要用epoll_ctl来重新设置socket fd的事件类型。

Reactor响应编程设计模式

Reactor封装了selector。

Reactor设计模式是event-driven architecture的一种实现方式,用于处理多个客户端并发的向服务器请求服务的场景。每种服务在服务器上可能由多个方法组成。Reactor会解耦并发请求的服务并分发给对应的时间处理器来处理。

Reactor模式的优点很明显:解耦、提升复用性、模块化、可移植性、事件驱动、细粒度的开发控制等。Reactor模式的缺点也很明显:模型复杂,涉及到内部回调、多线程处理、不容易调试、需要操作系统底层支持,因此导致不同操作系统可能会产生不一样的结果。

昨天NIO(请回顾上边文章链接)虽然使用到了selector,但是弊端仍然非常大,因为它处理读写事件的时候是串行处理的,如果正在处理十万条读写事件,又进入一个连接,就需要等待前边事件处理完成,性能不佳。优化:把读事件放入线程池处理(建立连接事件较快,不需要放入线程池)。但是,加了线程池之后仍然无法及时处理新加入的请求(线程不能开太多,会造成内存溢出)。这个时候就诞生了一个优秀的思想,主从reactor响应式模型。一个reactor用于建立连接,一个reactor去处理读事件。netty在此基础上又做了改进,一主多从,分发事件,这样效率就提高很多。以上描述分别为:单线程Reactor模型、多线程Reactor模型、主从Reactor模型。差别大家可以从图上比较一下:

 

来看一下netty的入门demo。从代码中更深入了解一下逻辑。

主要也就是创建启动对象、设定启动对象、绑定端口这三步。

    public static void main(String[] args) {
        //boosGroup只处理连接请求,真正的业务请求由workGroup处理
        //实质上是创建n个selector去处理,对应了上边所说的主从
        NioEventLoopGroup boosGroup = new NioEventLoopGroup(1);
        NioEventLoopGroup workGroup = new NioEventLoopGroup(8);
        try {
            //创建服务器端启动对象
            ServerBootstrap bootstrap = new ServerBootstrap();
            //链式编程配置启动对象
            bootstrap.group(boosGroup,workGroup)
                    .channel(NioServerSocketChannel.class) //设定通道实现
                    .option(ChannelOption.SO_BACKLOG,1024) //初始化服务器连接队列大小,将不能处理的放入队列
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            socketChannel.pipeline().addLast(new NettyServerHandler());//设置处理器,重在处理逻辑
                        }
                    });
            System.out.println("netty server start");
            //绑定端口,bind是异步,sync是保证异步执行完毕
            ChannelFuture sync = bootstrap.bind(9000).sync();
            //同上,关闭future
            sync.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            boosGroup.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }

事件实现,继承ChannelInboundHandlerAdapter重写自己想要是实现的业务。

public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("连接成功");
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf result = (ByteBuf) msg;
        byte[] bytesMsg = new byte[result.readableBytes()];
        result.readBytes(bytesMsg);
        String resultStr = new String(bytesMsg);
        System.out.println("数据为:"+resultStr);
        result.release();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值