zoukankan      html  css  js  c++  java
  • Netty4 学习笔记之一:客户端与服务端通信 demo

    前言

    因为以前在项目中使用过Mina框架,感受到了该框架的强大之处。于是在业余时间也学习了一下Netty。因为Netty的主要版本是Netty3和Netty4(Netty5已经被取消了),所以我就直接学习Netty4。在本文中演示的就是Netty的一个简单demo。

    开发准备

    Netty4的官方网站是:http://netty.io/
    本文使用的是Netty4.1。
    由于Netty4.1版本需要JDK1.7,在使用JDK1.6时,会有一些bug,所以推荐使用JDK1.7。

    因为Netty和Mina都是Trustin Lee的作品,所以在很多方面都十分相似,他们线程模型也是基本一致,采用了Reactors in threads模型,即Main Reactor + Sub Reactors的模式。

    所以在开发上,很多都可以相互借鉴。

    服务端

    首先完成Netty服务端相关开发,和Mina一样。
    主要由两个部分组成: 配置服务端的基本信息以及实现业务逻辑处理。
    如果需要,还有filter过滤器。

    服务端代码

    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    
    /**
     * 
    * Title: NettyServer
    * Description: Netty服务端
    * Version:1.0.0  
    * @author Administrator
    * @date 2017-8-31
     */
    public class NettyServer {
            private static final int port = 6789; //设置服务端端口
            private static  EventLoopGroup group = new NioEventLoopGroup();   // 通过nio方式来接收连接和处理连接   
            private static  ServerBootstrap b = new ServerBootstrap();
    
            /**
             * Netty创建全部都是实现自AbstractBootstrap。
             * 客户端的是Bootstrap,服务端的则是    ServerBootstrap。
             **/
            public static void main(String[] args) throws InterruptedException {
                try {
                    b.group(group);
                    b.channel(NioServerSocketChannel.class);
                    b.childHandler(new NettyServerFilter()); //设置过滤器
                    // 服务器绑定端口监听
                    ChannelFuture f = b.bind(port).sync();
                    System.out.println("服务端启动成功...");
                    // 监听服务器关闭监听
                    f.channel().closeFuture().sync();
                } finally {
                    group.shutdownGracefully(); ////关闭EventLoopGroup,释放掉所有资源包括创建的线程  
                }
            }
    }

    服务端业务逻辑

    import java.net.InetAddress;
    import java.util.Date;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    
    /**
     * 
    * Title: HelloServerHandler
    * Description:  服务端业务逻辑
    * Version:1.0.0  
    * @author Administrator
    * @date 2017-8-31
     */
    public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
        /*
         * 收到消息时,返回信息
         */
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg)
                throws Exception {
            // 收到消息直接打印输出
            System.out.println("服务端接受的消息 : " + msg);
            if("quit".equals(msg)){//服务端断开的条件
                ctx.close();
            }
            Date date=new Date();
            // 返回客户端消息
            ctx.writeAndFlush(date+"
    ");
        }
    
        /*
         * 建立连接时,返回消息
         */
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("连接的客户端地址:" + ctx.channel().remoteAddress());
            ctx.writeAndFlush("客户端"+ InetAddress.getLocalHost().getHostName() + "成功与服务端建立连接! 
    ");
            super.channelActive(ctx);
        }
    }

    服务端过滤器

    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.handler.codec.DelimiterBasedFrameDecoder;
    import io.netty.handler.codec.Delimiters;
    import io.netty.handler.codec.string.StringDecoder;
    import io.netty.handler.codec.string.StringEncoder;
    
    /**
      * 
     * Title: HelloServerInitializer
     * Description: Netty 服务端过滤器
     * Version:1.0.0  
     * @author Administrator
     * @date 2017-8-31
      */
    public class NettyServerFilter extends ChannelInitializer<SocketChannel> {
    
         @Override
         protected void initChannel(SocketChannel ch) throws Exception {
             ChannelPipeline ph = ch.pipeline();
             // 以("
    ")为结尾分割的 解码器
             ph.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
             // 解码和编码,应和客户端一致
             ph.addLast("decoder", new StringDecoder());
             ph.addLast("encoder", new StringEncoder());
             ph.addLast("handler", new NettyServerHandler());// 服务端业务逻辑
         }
     }

    客户端

    客户端的主要工作是
    1,连接到服务端
    2,向服务端发送数据数据
    3,处理服务端返回的数据
    4,关闭连接
    而且客户端相关代码也和服务端类似。

    客户端

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.Channel;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioSocketChannel;
    
    import java.io.IOException;
    /**
     * 
    * Title: NettyClient
    * Description: Netty客户端 
    * Version:1.0.0  
    * @author Administrator
    * @date 2017-8-31
     */
    public class NettyClient {
    
        public static String host = "127.0.0.1";  //ip地址
        public static int port = 6789;          //端口
        /// 通过nio方式来接收连接和处理连接   
        private static EventLoopGroup group = new NioEventLoopGroup(); 
        private static  Bootstrap b = new Bootstrap();
        private static Channel ch;
    
        /**
         * Netty创建全部都是实现自AbstractBootstrap。
         * 客户端的是Bootstrap,服务端的则是    ServerBootstrap。
         **/
        public static void main(String[] args) throws InterruptedException, IOException { 
                System.out.println("客户端成功启动...");
                b.group(group);
                b.channel(NioSocketChannel.class);
                b.handler(new NettyClientFilter());
                // 连接服务端
                ch = b.connect(host, port).sync().channel();
                star();
        }
    
        public static void star() throws IOException{
            String str="Hello Netty";
            ch.writeAndFlush(str+ "
    ");
            System.out.println("客户端发送数据:"+str);
       }
    
    }

    客户端业务逻辑实现

    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    
    /**
     * 
    * Title: NettyClientHandler
    * Description: 客户端业务逻辑实现
    * Version:1.0.0  
    * @author Administrator
    * @date 2017-8-31
     */
    public class NettyClientHandler extends SimpleChannelInboundHandler<String> {
    
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {  
            System.out.println("客户端接受的消息: " + msg);
        }
    
        //
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("正在连接... ");
            super.channelActive(ctx);
        }
    
        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("连接关闭! ");
            super.channelInactive(ctx);
        }
    }

    客户端过滤器

    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.handler.codec.DelimiterBasedFrameDecoder;
    import io.netty.handler.codec.Delimiters;
    import io.netty.handler.codec.string.StringDecoder;
    import io.netty.handler.codec.string.StringEncoder;
    /**
     * 
    * Title: NettyClientFilter
    * Description: Netty客户端 过滤器
    * Version:1.0.0  
    * @author Administrator
    * @date 2017-8-31
     */
    public class NettyClientFilter extends ChannelInitializer<SocketChannel> {
    
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline ph = ch.pipeline();
            /*
             * 解码和编码,应和服务端一致
             * */
            ph.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
            ph.addLast("decoder", new StringDecoder());
            ph.addLast("encoder", new StringEncoder());
            ph.addLast("handler", new NettyClientHandler()); //客户端的逻辑
        }
    }

    效果实现图

    服务端

    这里写图片描述

    客户端

    这里写图片描述

    demo教程到这里就结束了,如果有什么问题,欢迎提出!

    该项目我放在github上了,有兴趣的可以看看!https://github.com/xuwujing/Netty

  • 相关阅读:
    COM 组件创建实例失败,原因是出现以下错误: c001f011 (Microsoft.SqlServer.ManagedDTS)
    df: `/root/.gvfs': Permission denied
    ora-03113 end-of-file on communication channel 故障处理
    ESXi克隆虚拟机时网卡需要重新设置的问题
    Spark重点难点知识总结
    Hive,Hive on Spark和SparkSQL区别
    Spark分区数、task数目、core数目、worker节点数目、executor数目梳理
    spark RDD中的partition和hdfs中的block的关系
    Spark容错机制
    【干货】大数据框架整理
  • 原文地址:https://www.cnblogs.com/xuwujing/p/7536702.html
Copyright © 2011-2022 走看看