栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

Netty学习笔记(一) 客户端与服务端的搭建

Netty学习笔记(一) 客户端与服务端的搭建

Netty学习笔记(一) 客户端与服务端的搭建 客户端
ChannelFuture channelFuture = new Bootstrap()
                .group(new NioEventLoopGroup())
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        nioSocketChannel.pipeline().addLast(new StringEncoder());
                    }
                })
                // connect 异步非阻塞线程
                .connect(new InetSocketAddress("localhost", 8080));
        // 同步阻塞,等待nio线程建立连接
//        channelFuture.sync();
//        Channel channel = channelFuture.channel();
//        channel.writeAndFlush("hello world");

        //异步处理 addListener
        channelFuture.addListener(new ChannelFutureListener() {
            // nio建立连接后执行
            @Override
            public void operationComplete(ChannelFuture channelFuture) throws Exception {
                Channel channel = channelFuture.channel();
                channel.writeAndFlush("ojbk");
            }
        });

上边这段程序就是Netty客户端的一段搭建的代码,一句句来看,

new Bootstrap就是开始创建一个启动类,那么这个启动类需要哪些配置呢?

首先,加载事件循环组EventLoopGroup,这里我们可以指定bossEventLoop和WorkerEventLoop,当然,不指定的话可以那么连接读写由同一个事件循环处理了就好,通过链式调用 .group加载进启动类

有group了,那么group管理哪个channel呢?,我们通过 . channel指定管理的channel类型

同时我们还要指定channel在建立连接后会进行哪些处理,需要指定handler

最后在进行connect的一个链接;

这一段结束完之后,我们就创建了一个channelFuture,其实我们见到Future就知道,这其实是一个异步类,因为在整个Netty中,所有的io操作都是异步的,所以我们需要一种用于在之后的某个时间确定其结果的方法,(因为直接将之转为channel并发送数据,我们并不知道是EventLoop的哪个线程来处理的)我们有两种方法,可以将channelFuture进行一个处理,进行收发数据的需要。首先,异步转同步,channelFuture.sysc() 方法就是将channelFuture转为同步方法,随后进行消息发送,当然,异步转同步肯定不是一种很优雅的解决方式,那么怎么优雅呢?,异步处理,怎么异步处理呢?其实Netty的ChannelFuture提供了addListener接口来配置监听,当EventLoop执行完操作,建立好连接后,那么哪个线程执行的,哪个线程来处理listener中的方法,在这个方法里,我们可以去write。值得注意的是,channel的write,也是一个异步操作,当客户端write后,他并不会主动去发送数据,什么时候会发呢?flush触发,也就是说,你可以一个channe不停地write,最后再执行一个flush,将之前的数据发出去,当然,要想马上发,那就是writeAndFlush()

ok,服务端

服务端

先上代码

 // 服务器启动,负责组装netty组件
        new ServerBootstrap()
                .group(new NioEventLoopGroup()) // BossEventloop 处理可连接事件  workEventloop 处理可读事件
                .channel(NioServerSocketChannel.class) // 选择服务器得ServerSocketChannel实现
                // 决定worker进行哪些操作
                // ChannelInitializer 初始化channel
                .childHandler(new ChannelInitializer() {
                    @Override
                    protected void initChannel(NioSocketChannel nioSocketChannel) throws Exception {
                        nioSocketChannel.pipeline().addLast(new StringDecoder()); // bytebuf转字符串
                        //自定义handler
                        nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                System.out.println(msg);
                                super.channelRead(ctx, msg);
                                //ctx.fireChannelRead(msg);//交给后续handler执行
                            }
                        });
                    }
                })
                .bind(8080);

这个,得和client对照着看,启动类不一样,服务端启的是ServerBootStrap(),后边的group,channel和childHandler都一样,那么服务端主要做一个消息的接收,怎么处理?就是利用childHandler去注册handler接收信息,比如说上段代码的new ChannelInitializer里边的initChannel,管道建立初始化的时候怎么做?EventLoop执行哪些handler?handler中做什么事?这些我们都在initChannel方法中去处理

nioSocketChannel.pipeline().addLast(new ChannelInboundHandlerAdapter(){
                            @Override
                            public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
                                System.out.println(msg);
                                super.channelRead(ctx, msg);
                                //ctx.fireChannelRead(msg);//交给后续handler执行
                            }
                        });

这一段,就是想socketchannel中添加了一个接收并处理消息的handler。

ok,发完了,接收到了,怎么关呢?

关闭客户端

我们都知道,Netty处理IO操作都是一步的,那么我们能直接在主程序里边去channe.close()吗?肯定不行,关不掉,那么怎么处理?首选,同步关闭

channel.closeFuture().sysc()

这一接口就是将channel转成同步,阻塞主线程,等待eventLoop执行完毕,进行后续操作

在这之后,worker.gracefullyShutdow() 优雅结束

二,异步处理

ChannelFuture closeFuture = channel.closeFuture();
                        closeFuture.addListener((future)->{
                            log.debug("closingggggggggg");
                            eventExecutors.shutdownGracefully();//group结束
                        });

还是addListener接口处理,哪个线程执行完了,优雅关闭。

当然,上边客户端,服务端的代码都是用了匿名内部类,只有一个方法,当然可以用lambda表达式去优化。

代码仅供批判

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/700717.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号