zoukankan      html  css  js  c++  java
  • Netty的Echo示例

    1.简述

      Echo客户端和服务器之间的交互是非常简单的。在客户端建立一个连接之后,它会向服务器发送一个或多个消息,反过来,服务器又会将每个消息回送给客户端。虽然它本身看起来好像用处不大,但它充分地体现了客户端/服务器系统中典型的请求-响应交互模式。

      通过同时实现客户端和服务器,我们将能够更加全面地理解Netty的API。

    2.示例代码

    (1)Maven引入

    <dependencies>
            <!-- https://mvnrepository.com/artifact/io.netty/netty-all -->
            <dependency>
                <groupId>io.netty</groupId>
                <artifactId>netty-all</artifactId>
                <version>4.1.36.Final</version>
            </dependency>
        </dependencies>
    View Code

    (2)服务器

      EchoServer

    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;
    import java.net.InetSocketAddress;
    
    /**
     * @description: echo服务器
     **/
    public class EchoServer {
        private static final int port = 8080;//服务器监听端口
    
        public void start() throws InterruptedException {
            ServerBootstrap server = new ServerBootstrap();//引导辅助程序
            EventLoopGroup group = new NioEventLoopGroup();//通过nio方式来接收连接和处理连接
            try {
                server.group(group);
                server.channel(NioServerSocketChannel.class);//设置nio类型的channel
                server.localAddress(new InetSocketAddress(port));//设置监听端口
                server.childHandler(new ChannelInitializer<SocketChannel>() {//有连接到达时会创建一个channel
                    protected void initChannel(SocketChannel ch) {
                        //pipeline管理channel中的Handler,在channel队列中添加一个handler来处理业务
                        ch.pipeline().addLast("serverHandler", new EchoServerHandler());
                    }
                });
                ChannelFuture f = server.bind().sync();//配置完成,开始绑定server,通过调用sync同步方法阻塞直到绑定成功
                System.out.println(EchoServer.class.getName() + " 开始监听 " + f.channel().localAddress());
                f.channel().closeFuture().sync();//应用程序会一直等待,直到channel关闭
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                group.shutdownGracefully().sync();//关闭EventLoopGroup,释放掉所有资源包括创建的线程
            }
        }
    
        public static void main(String[] args) {
            try {
                new EchoServer().start();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    View Code

      EchoServerHandler

    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 io.netty.util.CharsetUtil;
    
    /**
     * @description: echo服务器业务处理类
     * Sharable表示此对象在channel间共享
     **/
    @ChannelHandler.Sharable//注解@Sharable可以让它在channels间共享
    public class EchoServerHandler extends ChannelInboundHandlerAdapter {
    
        public void channelRead(ChannelHandlerContext ctx, Object msg) {
            ByteBuf in = (ByteBuf) msg;
            System.out.println("服务器收到"+ctx.channel().localAddress()+"数据 :" + in.toString(CharsetUtil.UTF_8));
            //将接收到的消息写给发送者,即客户端,而不冲刷出站消息
            ctx.write(msg);
        }
    
        public void channelReadComplete(ChannelHandlerContext ctx) {
            //将未决消息冲刷到远程节点,并且关闭该Channel
            ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
        }
    
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            //cause.printStackTrace();//捕捉异常信息
            System.out.println(cause.getMessage());
            ctx.close();//出现异常时关闭channel
        }
    }
    View Code

    (3)客户端

      EchoClient

    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelFutureListener;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;
    import java.net.InetSocketAddress;
    
    /**
     * @description: echo客户端
     **/
    public class EchoClient {
        private final String host;
        private final int port;
    
        public EchoClient(String host, int port) {
            this.host = host;
            this.port = port;
        }
    
        public void start() throws Exception {
            EventLoopGroup group = new NioEventLoopGroup();
            try {
                Bootstrap b = new Bootstrap();
                b.group(group);
                b.channel(NioSocketChannel.class);
                b.remoteAddress(new InetSocketAddress(host, port));
                b.handler(new ChannelInitializer<SocketChannel>() {
                    public void initChannel(SocketChannel ch) {
                        ch.pipeline().addLast(new EchoClientHandler());
                    }
                });
                ChannelFuture f = b.connect().sync();
                f.addListener(new ChannelFutureListener() {
                    public void operationComplete(ChannelFuture future) {
                        if(future.isSuccess()){
                            System.out.println("连接echo服务器成功");
                        }else{
                            System.out.println("连接echo服务器失败:"+future.cause().getMessage());
                            //future.cause().printStackTrace();
                        }
                    }
                });
                f.channel().closeFuture().sync();
            } finally {
                group.shutdownGracefully().sync();
            }
        }
    
        public static void main(String[] args) throws Exception {
            for (int i=0;i<100;i++) {
                new Thread(new Runnable() {
                    public void run() {
                        try {
                            new EchoClient("127.0.0.1", 8080).start();
                        }catch (Exception e){
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
    }
    View Code

      EchoClientHandler

    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 io.netty.util.CharsetUtil;
    
    /**
     * @description: echo客户端业务处理类
     **/
    @ChannelHandler.Sharable
    public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
        /**
         *此方法会在连接到服务器后被调用
         * */
        public void channelActive(ChannelHandlerContext ctx) {
            ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!", CharsetUtil.UTF_8));
        }
    
        /**
         *此方法会在接收到服务器数据后调用
         * */
        public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) {
            System.out.println("客户端收到数据: " + in.toString(CharsetUtil.UTF_8));
        }
    
        /**
         *捕捉到异常
         * */
        public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
            cause.printStackTrace();
            ctx.close();
        }
    
    }
    View Code
  • 相关阅读:
    EF中读取随机数据的问题
    【坐在马桶上看算法】算法3:最常用的排序——快速排序
    C#递归算法
    机器学习策略(二)---误差分析、训练集与开发测试集不相配怎么办、迁移学习/多任务学习、端到端深度学习
    机器学习策略(一)---正交化、评估指标、优化指标、训练与测试集数据集大小、可避免误差
    改善深层神经网络的优化算法:mini-batch梯度下降、指数加权平均、动量梯度下降、RMSprop、Adam优化、学习率衰减
    具有单隐藏层的二分类神经网络
    神经网络前向后向传播(理论与实战)
    梯度消失与梯度爆炸---如何选择随机初始权重
    正则化输入
  • 原文地址:https://www.cnblogs.com/bl123/p/15606520.html
Copyright © 2011-2022 走看看