美文网首页
初尝Netty(一):Echo通信

初尝Netty(一):Echo通信

作者: 请不要问我是谁 | 来源:发表于2019-01-06 19:33 被阅读0次

    EchoServer与EchoClient编写

    客户端发送一个消息给服务端,服务端收到消息后返回一个消息

    MyServer

    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;
    import io.netty.handler.logging.LogLevel;
    import io.netty.handler.logging.LoggingHandler;
    
    /**
     * @author kun
     */
    public class MyServer{
        public static void main(String[] args){
            # 两个线程工作组,一般在Server端创建两个,在Client端创建一个
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                # Netty是通过bootstrap引导完成配置
                ServerBootstrap serverBootstrap = new ServerBootstrap();
                serverBootstrap.group(bossGroup, workerGroup)
                        .channel(NioServerSocketChannel.class)
                        .handler(new LoggingHandler(LogLevel.WARN))
                        # 初始化
                        .childHandler(new MyServerInitializer());
                # 绑定端口
                ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
                channelFuture.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                bossGroup.shutdownGracefully();
                workerGroup.shutdownGracefully();
            }
        }
    }
    

    MyServerInitializer

    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
    import io.netty.handler.codec.LengthFieldPrepender;
    import io.netty.handler.codec.string.StringDecoder;
    import io.netty.handler.codec.string.StringEncoder;
    import io.netty.util.CharsetUtil;
    
    /**
     * @author kun
     * 初始化的过程就是添加一系列的Handler,而这些Handler就是来完成通信的任务,根据不同的目的选用不同的Handler。
     * 这些Handler一部分是Netty已经实现了的,加进来就行,也可以根据自己的业务逻辑编写自己的Handler。
     */
    public class MyServerInitializer extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            # 通用拆包器
            pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
            # 通用编码器
            pipeline.addLast(new LengthFieldPrepender(4));
            # 字符串解码
            pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
            # 字符串编码
            pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
            # 添加自己编写的Handler
            pipeline.addLast(new MyServerHandler());
        }
    }
    

    MyServerHandler

    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    
    import java.util.UUID;
    
    /**
     * @author kun
     */
    public class MyServerHandler extends SimpleChannelInboundHandler<String> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            # 服务器收到消息后执行
            System.out.println(ctx.channel().remoteAddress()+", "+msg);
            # 服务器发送信息,ctx用来获取通道的相关信息
            ctx.channel().writeAndFlush("from server: "+ UUID.randomUUID());
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            # 发生异常
            cause.printStackTrace();
            ctx.close();
        }
    }
    

    Client端的编写步骤与Server端相同,一样分成主函数,Initializer,Handler三部分
    MyClinet

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.nio.NioSocketChannel;
    
    /**
     * @author kun
     */
    public class MyClient {
        public static void main(String[] args) {
            EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
            try {
                Bootstrap bootstrap = new Bootstrap();
                bootstrap.group(eventLoopGroup)
                        .channel(NioSocketChannel.class)
                        .handler(new MyClientInitializer());
                # 客户端使用函数connect连接服务器
                ChannelFuture channelFuture = bootstrap.connect("localhost", 8899).sync();
                channelFuture.channel().closeFuture().sync();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }finally {
                eventLoopGroup.shutdownGracefully();
            }
        }
    }
    

    MyClinetInitializer

    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelPipeline;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
    import io.netty.handler.codec.LengthFieldPrepender;
    import io.netty.handler.codec.string.StringDecoder;
    import io.netty.handler.codec.string.StringEncoder;
    import io.netty.util.CharsetUtil;
    
    /**
     * @author kun
     * 这部分与服务器端基本相同
     */
    public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            ChannelPipeline pipeline = ch.pipeline();
            pipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
            pipeline.addLast(new LengthFieldPrepender(4));
            pipeline.addLast(new StringDecoder(CharsetUtil.UTF_8));
            pipeline.addLast(new StringEncoder(CharsetUtil.UTF_8));
            pipeline.addLast(new MyClientHandler());
        }
    }
    

    MyClinerHandler

    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.SimpleChannelInboundHandler;
    
    import java.time.LocalDateTime;
    
    /**
     * @author asus
     */
    public class MyClientHandler extends SimpleChannelInboundHandler<String> {
        @Override
        protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
            System.out.println(ctx.channel().remoteAddress());
            System.out.println("client output:"+msg);
            ctx.writeAndFlush("from client:"+ LocalDateTime.now());
        }
        # 当与服务器通道建立后,由客户端先发起通信
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            ctx.writeAndFlush("来自于客户端的问候!");
        }
    
        @Override
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
            cause.printStackTrace();
            ctx.close();
        }
    }
    

    相关文章

      网友评论

          本文标题:初尝Netty(一):Echo通信

          本文链接:https://www.haomeiwen.com/subject/adxerqtx.html