码迷,mamicode.com
首页 > Web开发 > 详细

初识Netty -- 基于Netty的DayTime时间服务器

时间:2017-10-24 22:48:40      阅读:360      评论:0      收藏:0      [点我收藏+]

标签:java   netty   

1. 关于Netty的基本认知:

JDK 1.4推出Java NIO之前,基于Java的所有Socket通信都采用的BIO(同步阻塞式IO),同步阻塞式IO存在巨大的性能和可靠性瓶颈,无法适用于高性能服务器的开发。虽然后来出现了伪异步I/O通信框架,但它仅仅是对之前I/O线程模型的一个简单优化。    

JDK 1.4之后,Java诞生了NIO,也就是引入了java.nio类库,提供了很多进行异步I/O开发的API。随着java NIO的发展,对于高性能的服务器开发来说,java原生NIO仍然存在许多问题,甚至出现了非常严重的epoll bug。另外Java原生NIO的API类库繁杂,上手难度大,并非开发者心中理想的框架。

Netty是业界最流行的NIO框架之一,它经历的大规模的商业应用考验,在互联网、大数据、网络游戏等众多行业已经得到了成功商用,因此Netty逐渐成为了Java NIO编程的首选框架。技术分享


2. Netty开发环境搭建

可以使用maven自动构建java项目,本例中只需一个netty jar包,手动导入即可。

下载Netty jar包并导入Java项目中。Netty jar包到http://netty.io/ netty官网)的download页面,本例中就使用最新的netty-4.1.16.Final,在解压之后的文件夹中找到netty-all-4.1.16.Final.jar,路径netty-4.1.16.Final > jar > all-in-one 

技术分享

在java项目中创建lib文件夹,导入netty jar包(jar包要作为库文件导入)。

技术分享

本例中需要创建两个项目,分别是时间服务器和时间客户端。

技术分享


3. 基于Netty的DayTime时间服务器与客户端架构

DayTime服务器只需一个Server启动类和一个业务逻辑处理类(处理客户端请求)即可,客户端也只需一个Client启动类和一个业务逻辑处理类(向服务器发送请求并处理服务器响应),参考下图。

技术分享

①TimeServer.java(服务器启动类)源码如下:

技术分享

--------------------------------------------------------------------------------------------------------------------

public class TimeServer {


    public void bind(int port) throws Exception {

        //配置服务端NIO线程组。

        EventLoopGroup bossGroup = new NioEventLoopGroup();

        EventLoopGroup workerGroup = new NioEventLoopGroup();


        try {

            ServerBootstrap serverBootstrap = new ServerBootstrap();

            serverBootstrap.group(bossGroup, workerGroup)

                    .channel(NioServerSocketChannel.class)

                    .option(ChannelOption.SO_BACKLOG, 1024)

                    .childHandler(new ChildChannelHandler());

            //绑定端口,同步等待成功。

            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

            //等待服务端监听端口关闭。

            channelFuture.channel().closeFuture().sync();

        } finally {

            //优雅退出,释放线程池资源。

            bossGroup.shutdownGracefully();

            workerGroup.shutdownGracefully();

        }

    }

--------------------------------------------------------------------------------------------------------------------

②TimeServerHandler.java(处理客户端请求)源码如下:

技术分享

--------------------------------------------------------------------------------------------------------------------

public class TimeServerHandler extends ChannelInboundHandlerAdapter {

    @Override

    public void channelRead(ChannelHandlerContext channelHandlerContext, Object msg)

            throws Exception {

        ByteBuf buf = (ByteBuf) msg;

        byte[] req = new byte[buf.readableBytes()];

        buf.readBytes(req);

        String body = new String(req, "UTF-8");

        System.out.println("时间服务器收到请求:" + body);

        String currentTime = "QUERY TIME ORDER".equalsIgnoreCase(body) ? new Date(

                System.currentTimeMillis()).toString() : "BAD ORDER";

        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());

        channelHandlerContext.write(resp);

    }


    @Override

    public void channelReadComplete(ChannelHandlerContext channelHandlerContext)

            throws Exception {

        channelHandlerContext.flush();

    }


    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {

        ctx.close();

    }

}

--------------------------------------------------------------------------------------------------------------------

③TimeClient.java(客户端启动类)源码如下(流程与服务器启动类类似):

技术分享

--------------------------------------------------------------------------------------------------------------------

public class TimeClient {

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

        //配置客户端NIO线程组。

        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {

            Bootstrap bootstrap = new Bootstrap();

            bootstrap.group(eventLoopGroup).channel(NioSocketChannel.class)

                    .option(ChannelOption.TCP_NODELAY, true)

                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override

                        protected void initChannel(SocketChannel socketChannel) throws Exception {

                            socketChannel.pipeline().addLast(new TimeClientHandler());

                        }

                    });


            //发起异步连接操作。

            ChannelFuture channelFuture = bootstrap.connect(host, port).sync();


            //等待客户端链路关闭。

            channelFuture.channel().closeFuture().sync();

        } finally {

            //优雅推出,释放NIO线程组。

            eventLoopGroup.shutdownGracefully();

        }

    }


    public static void main(String[] args) throws Exception {

        int port = 8080;

        if (args != null && args.length > 0) {

            try {

                port = Integer.valueOf(args[0]);

            } catch (NumberFormatException e) {

                //采用默认值。

            }

        }

        new TimeClient().connect(port, "127.0.0.1");

    }

}

--------------------------------------------------------------------------------------------------------------------

④TimeClientHandler.java(客户端业务逻辑处理类)源码如下:

技术分享

--------------------------------------------------------------------------------------------------------------------

public class TimeClientHandler extends ChannelInboundHandlerAdapter {

    private static final Logger logger = Logger

            .getLogger(TimeClientHandler.class.getName());


    private final ByteBuf firstMessage;


    public TimeClientHandler() {

        byte[] request = "QUERY TIME ORDER".getBytes();

        firstMessage = Unpooled.buffer(request.length);

        firstMessage.writeBytes(request);

    }


    @Override

    public void channelActive(ChannelHandlerContext ctx) {

        ctx.writeAndFlush(firstMessage);

    }


    @Override

    public void channelRead(ChannelHandlerContext ctx, Object msg)

            throws Exception {

        ByteBuf byteBuf = (ByteBuf) msg;

        byte[] req = new byte[byteBuf.readableBytes()];

        byteBuf.readBytes(req);

        String body = new String(req, "UTF-8");

        System.out.println("Now is:" + body);

    }


    @Override

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {

        // 释放资源

        logger.warning("Unexpected exception from downstream : " + cause.getMessage());

        ctx.close();

    }

}

--------------------------------------------------------------------------------------------------------------------

4. 启动服务器,运行客户端

先启动服务器,然后运行客户端,此时服务收到客户端的获取时间的请求“QUERY TIME ORDER”,会在控制台输出。客户端此时会接收到服务器响应消息,也就是当前服务器时间。

技术分享


本文出自 “一赫。” 博客,谢绝转载!

初识Netty -- 基于Netty的DayTime时间服务器

标签:java   netty   

原文地址:http://consolas.blog.51cto.com/9388583/1975711

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!