• 第一款Netty应用程序


      这边开始写一个Demo来熟悉下Netty的使用,Demo主要为写一个Echo服务器来实现服务器和客户端之间的交流问题

      ChannelHandler是一个接口簇的父接口,它的实现负责接收并响应事件通知。在Netty应用程序中,所有的数据处理逻辑都是包含在这下核心抽象的实现中。需要响应传入的消息,那么就至少需要实现一个ChannelInboundHandler接口,用来定义入站的事件。

      ChannelRead()——对于每个传入的消息都调用

      ChannelReadComplete()——通知ChannelInboundHandler最后一次对ChannelRead()调用是当前批量读取中的最后一条消息

      exceptionCaught()——在读取操作期间,有异常抛出时候会进行调用

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelFutureListener;
    import io.netty.channel.ChannelHandler;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;
    
    import java.nio.charset.Charset;
    
    /**
     * description: EchoServerHandler
     * date: 2021/4/21 17:43
     *
     * @author: SmartCat
     * version: 1.0.0
     */
    @ChannelHandler.Sharable
    public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg){
            ByteBuf in = (ByteBuf) msg;
            System.out.println (in.toString (Charset.defaultCharset ()));
            ctx.write (in);
        }
    
        @Override
        public void channelReadComplete(ChannelHandlerContext ctx){
            ctx.writeAndFlush (Unpooled.EMPTY_BUFFER)
                    .addListener (ChannelFutureListener.CLOSE);
        }
    
        @Override
        public void exceptionCaught (ChannelHandlerContext ctx, Throwable cause){
            cause.printStackTrace ();
            ctx.close ();
        }
    }

      ChannelInboundHandlerAdapter有一个直观的API,可以通过重写它的方法来对重新挂钩到事件生命周期的恰当点上。


      开始写一个引导类,来对Netty进行启动。

      引导类的绑定到服务器将在其上监听并接受传入连接请求的端口;配置Channel,将有关的入站这消息通知给EchoServerHandler实例。

    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    
    import java.net.InetSocketAddress;
    
    /**
     * description: EchoServer
     * date: 2021/4/21 17:57
     *
     * @author: SmartCat
     * version: 1.0.0
     */
    public class EchoServer {
        private int port=8080;
        public EchoServer(int port){
            this.port = port;
        }
    
        public static void main(String[] args) throws InterruptedException {
            new EchoServer (8088).start();
        }
    
        private void start() throws InterruptedException {
            EchoServerHandler echoServerHandler = new EchoServerHandler ();
         //NioEventLoopGroup无参构建的时候调用MultithreadEventLoopGroup的构造参数,默认的线程数是CPU个数的*2    NioEventLoopGroup group
    = new NioEventLoopGroup (); try{ ServerBootstrap serverBootstrap = new ServerBootstrap (); serverBootstrap.group(group) .channel (NioServerSocketChannel.class) .localAddress (new InetSocketAddress (8088))
                //新连接被接受的时候,一个新的Channel会被创建,ChannelInitializer会将一个你的EchoServerHandler的实例添加到该Channel的ChannelPipeline中 .childHandler (
    new ChannelInitializer<SocketChannel> () { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline ().addLast (echoServerHandler); } }); ChannelFuture f = serverBootstrap.bind ().sync (); f.channel ().closeFuture ().sync (); } catch (InterruptedException e) { e.printStackTrace (); } finally { group.shutdownGracefully ().sync (); } } }

       主要步骤:

      1.实现自己的Handler————>EchoServerHandler

      2.main()方法进行引导启动

      3.创建一个ServerBootStrap的实例以引导和绑定服务器

      4.创建并分配一个NioEventGroup实例线程组来进行事件的处理,接受新连接以及读写操作

      5.指定服务器绑定的本地的InetSocketAddress

      6.使用EchoServerHandler的实例初始化每一个新的Channel

      7.调用ServerBootStrap.bind()以绑定服务器


      然后建立一个自己的客户端

      和服务端一样,服务端对应的是ChannelInboundHandlerAdapter。客户端也是ChannelInboundHandlerAdapter(這邊使用的相對簡單的SimpleChannelInboundHandler)。重写的方法不同而已,客户端需要重写的是连接后,读,以及异常的处理

      

    import io.netty.buffer.ByteBuf;
    import io.netty.buffer.Unpooled;
    import io.netty.channel.ChannelHandler;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    
    import java.nio.charset.Charset;
    
    /**
     * description: EchoClinentHandler
     * date: 2021/4/21 18:11
     *
     * @author: SmartCat
     * version: 1.0.0
     */
    @ChannelHandler.Sharable
    public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf>{
    
        @Override
        public void channelActive(ChannelHandlerContext ctx){
            ctx.writeAndFlush (Unpooled.copiedBuffer ("Netty rocks", Charset.defaultCharset ()));
        }
        
        @Override
        protected void channelRead0(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf) throws Exception {
            System.out.println ("channelHandlerContext is get");
        }
        
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable t){
            t.printStackTrace ();
            ctx.close ();
        }
    }

      重写ChannelAdvice方法是为了在连接被调用的时候,数据将被写入服务器,重写ChannelRead0()方法是一个接收数据的时候进行的方法。

      为什么使用Simple.....不是EchoServerHandler中的那个呢?因为write是异步的,Simple帮我们又做了一层自动的刷新处理


      最后再建立一个客户端的启动引导类就可以完成了。

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    
    import java.net.InetSocketAddress;
    
    /**
     * description: EchoClient
     * date: 2021/4/21 18:27
     *
     * @author: SmartCat
     * version: 1.0.0
     */
    public class EchoClient {
    
    
        public void start() {
            NioEventLoopGroup group = new NioEventLoopGroup ();
            try {
                Bootstrap b = new Bootstrap ();
                b.group (group)
                        .channel (NioSocketChannel.class)
                        .remoteAddress (new InetSocketAddress ("127.0.0.1", 8088))
                        .handler (new ChannelInitializer<SocketChannel> () {
                            @Override
                            protected void initChannel(SocketChannel socketChannel) {
                                socketChannel.pipeline ().addLast (new EchoClientHandler ());
                            }
                        });
                ChannelFuture f = b.connect ().sync ();
                f.channel ().closeFuture ().sync ();
            } catch (InterruptedException e) {
                e.printStackTrace ();
            }
        }
    
        public static void main(String[] args) {
            new EchoClient ().start ();
        }
    }

      主要的要点:

      1.为了初始化客户端,创建一个BootStrap实例

      2.为进行实践处理分配了一个NioEventLoopGroup实例,其中实践处理包括创建新的连接以及处理入站和出站数据

      3.创建一个InetSocketAddress实例

      4.当连接被建立时,一个EchoClientHandler实例会被安装到ChannelPipeline中

    smartcat.994
  • 相关阅读:
    2020软件工程第四次作业
    软件工程第三次作业
    软件工程第二次作业
    软件工程第一次作业
    #数据挖掘与数据化运营实战#2.3数据挖掘技术以及在数据化运营中的应用
    #简单统计学#单样本t检验
    #简单统计学#加权平均数
    软件工程(2019)结对编程第二次作业
    软件工程(2019)结对编程第一次作业
    软件工程(2019)第三次个人作业
  • 原文地址:https://www.cnblogs.com/SmartCat994/p/14686506.html
Copyright © 2020-2023  润新知