zoukankan      html  css  js  c++  java
  • Netty异步编程模型上的同步调用




    看简单的一个小程序,说明什么是同步调用:所谓的同步调用就是调用一个方法,然后返回一个结果。(这个过程一直是阻塞的,直到返回值)。


    而netty中异步编程模型中不是同步调用,读写都是在handler中处理。


    关于同步调用和异步调用请参考http://blog.csdn.net/dan_blog/article/details/7897852


    服务器端程序


    package hello.netty.lyx.com;


    import io.netty.bootstrap.ServerBootstrap;
    import io.netty.channel.ChannelFuture;
    import io.netty.channel.ChannelInitializer;
    import io.netty.channel.ChannelOption;
    import io.netty.channel.EventLoopGroup;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioServerSocketChannel;


    public class HelloServer {
        public void start(int port) throws Exception {
            EventLoopGroup bossGroup = new NioEventLoopGroup();
            EventLoopGroup workerGroup = new NioEventLoopGroup();
            try {
                ServerBootstrap b = new ServerBootstrap();
                b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                        .childHandler(new ChannelInitializer<SocketChannel>() {
                            @Override
                            public void initChannel(SocketChannel ch) throws Exception {
                                // 注册handler
                                ch.pipeline().addLast(new HelloServerInHandler());
                            }
                        }).option(ChannelOption.SO_BACKLOG, 128);


                ChannelFuture f = b.bind(port).sync();
                f.channel().closeFuture().sync();


            } finally {
                workerGroup.shutdownGracefully();
                bossGroup.shutdownGracefully();
            }
        }


        public static void main(String[] args) throws Exception {
            HelloServer server = new HelloServer();
            server.start(9090);
        }
    }
    package hello.netty.lyx.com;


    import io.netty.buffer.ByteBuf;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;


    // 该handler是InboundHandler类型
    public class HelloServerInHandler extends ChannelInboundHandlerAdapter {
        @Override
        public boolean isSharable() {
            System.out.println("==============handler-sharable==============");
            return super.isSharable();
        }


        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel-register==============");
        }


        @Override
        public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel-unregister==============");
        }


        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel-active==============");
        }


        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel-inactive==============");
        }


        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {


            System.out.println("==============channel-read==============");


            ByteBuf result = (ByteBuf) msg;
            byte[] result1 = new byte[result.readableBytes()];
            // msg中存储的是ByteBuf类型的数据,把数据读取到byte[]中
            result.readBytes(result1);
            String resultStr = new String(result1);
            // 接收并打印客户端的信息
            System.out.println("Client said:" + resultStr);
            // 释放资源,这行很关键
            result.release();


            // 向客户端发送消息
            String response = "I am ok!";
            // 在当前场景下,发送的数据必须转换成ByteBuf数组
            ByteBuf encoded = ctx.alloc().buffer(4 * response.length());
            encoded.writeBytes(response.getBytes());
            ctx.writeAndFlush(encoded);
            ctx.close();
        }


        @Override
        public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel-read-complete==============");
            ctx.flush();
        }
    }
    客户端程序


    package hello.netty.lyx.com;


    import io.netty.bootstrap.Bootstrap;
    import io.netty.channel.*;
    import io.netty.channel.nio.NioEventLoopGroup;
    import io.netty.channel.socket.SocketChannel;
    import io.netty.channel.socket.nio.NioSocketChannel;


    /**
     * 1、Client向Server发送消息:Are you ok?
     * 2、Server接收客户端发送的消息,并打印出来。
     * 3、Server端向客户端发送消息:I am ok!
     * 4、Client接收Server端发送的消息,并打印出来,通讯结束。
     */


    public class HelloClient {


        StringBuffer message = new StringBuffer();


        public String connect(String host, int port) throws Exception {


            EventLoopGroup workerGroup = new NioEventLoopGroup();


            try {
                Bootstrap b = new Bootstrap();
                b.group(workerGroup);
                b.channel(NioSocketChannel.class);
    //            b.option(ChannelOption.AUTO_READ, false);
                b.handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new HelloClientIntHandler(message));
                    }
                });


                // Start the client.
                /**
                 * await()方法:Waits for this future to be completed.
                 * Waits for this future until it is done, and rethrows the cause of the failure if this future
                 * failed.
                 */
                ChannelFuture f = b.connect(host, port).channel().closeFuture().await();
                return message.toString();


            } finally {
                workerGroup.shutdownGracefully();
            }
        }


        public static void main(String[] args) throws Exception {
            HelloClient client = new HelloClient();
            System.out.println(">>>>>>>>>>"+client.connect("127.0.0.1", 9090).toString());
        }
    }
    package hello.netty.lyx.com;


    import io.netty.buffer.ByteBuf;
    import io.netty.channel.ChannelHandlerContext;
    import io.netty.channel.ChannelInboundHandlerAdapter;




    //InboundHandler类型
    public class HelloClientIntHandler extends ChannelInboundHandlerAdapter {


        public StringBuffer message;


        public HelloClientIntHandler(StringBuffer message) {
            this.message = message;
        }


        @Override
        public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel--register==============");
        }


        @Override
        public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel--unregistered==============");
        }


        @Override
        public void channelInactive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel--inactive==============");
        }


        // 连接成功后,向server发送消息
        @Override
        public void channelActive(ChannelHandlerContext ctx) throws Exception {
            System.out.println("==============channel--active==============");
            String msg = "Are you ok?";
            /**
             * 分配ByteBuf
             * Return the assigned {@link io.netty.buffer.ByteBufAllocator} which will be used to allocate {@link ByteBuf}s.
             */
            ByteBuf encoded = ctx.alloc().buffer(4 * msg.length());
            encoded.writeBytes(msg.getBytes());
            ctx.write(encoded);
            Thread.sleep(10000);
            ctx.flush();
        }


        // 接收server端的消息,并打印出来
        @Override
        public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
            System.out.println("==============channel--read==============");
            ByteBuf result = (ByteBuf) msg;
            byte[] result1 = new byte[result.readableBytes()];
            result.readBytes(result1);
            System.out.println("Server said:" + new String(result1));
            message.append(new String(result1));
            result.release();
        }
    }
    同步调用体现在这里,使用awaiit方法,一直等待Future的完成。


    ChannelFuture f = b.connect(host, port).channel().closeFuture().await();
    return message.toString();
    public static void main(String[] args) throws Exception {
        HelloClient client = new HelloClient();
        System.out.println(">>>>>>>>>>"+client.connect("127.0.0.1", 9090).toString());
    }
    当条用connect方法时,直接返回服务器的数据。


    看运行结果,可以体会到netty的同步效果


    服务器端打印:


    ==============handler-sharable==============


    ==============channel-register==============


    ==============channel-active==============


    ==============channel-read==============


    Client said:Are you ok?


    thread sleep end


    ==============channel-read-complete==============


    ==============channel-inactive==============


    ==============channel-unregister==============






    客户端打印


    ==============channel--register==============


    ==============channel--active==============


    ==============channel--read==============


    Server said:I am ok!


    ==============channel--inactive==============


    ==============channel--unregistered==============


    >>>>>>>>>>I am ok!






    Process finished with exit code 0


    客户端有可能还会出现这种结果:


    ==============channel--register==============


    ==============channel--active==============


    ==============channel--read==============


    Server said:I am ok!


    >>>>>>>>>>I am ok!


    ==============channel--inactive==============


    ==============channel--unregistered==============


    可以体会到同步调用的效果,虽然是在netty的异步编程模型上。


    ==============END==============
  • 相关阅读:
    Red Hat Enterprise Linux 7的新功能
    Unix/Linux环境C编程入门教程(41) C语言库函数的文件操作详解
    Unix/Linux环境C编程入门教程(40) 初识文件操作
    hadoop 1.2.1 安装步骤 伪分布式
    heritrix 3.2.0 -- 环境搭建
    nyoj301递推求值
    nyoj301递推求值
    luogu1962斐波那契数列
    矩阵快速幂模板
    矩阵快速幂模板
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317918.html
Copyright © 2011-2022 走看看