Netty初体验

来源:互联网 发布:javascript 数组splice 编辑:程序博客网 时间:2024/06/05 15:40

1. 什么是Netty?

Netty是一个异步事件驱动网络应用框架,为快速开发可维护的高性能协议服务端和客户端程序而生的。它极大地简化和流程化了TCP/UDP Socket网络编程。Netty在设计时,从许多协议中借鉴了大量经验,例如FTP、SMTP、HTTP和许多基于二进制或文本协议,成功的找到了一条不需要妥协的路而不失去开发的简易、高性能、稳定性和灵活性。

在使用Netty前,你需要对Java NIO有一定了解,Netty是基于NIO开发的。

这里写图片描述

2. 起步

这章将要通过几个简单的例子,让你快速起步去了解Netty的核心结构。当你学完这章,你将能够写基于Netty的客户端和服务端程序。需要注意的是,你的JDK版本需要最低1.6的版本。在你学习这章时,有任何疑问,可以查看相关API文档,那里你会找到你想要的答案。这里给出API的链接,好了,让我们开始吧!

2.1 Hello Netty服务端和客户端

首先是EchoServer程序,代码如下:

package com.leel0330.netty.echo;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.*;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.serialization.ClassResolvers;import io.netty.handler.codec.serialization.ObjectDecoder;import io.netty.handler.codec.serialization.ObjectEncoder;import io.netty.handler.logging.LogLevel;import io.netty.handler.logging.LoggingHandler;public class EchoServer {    public static void main(String[] args){        final int PORT = 6666;        EventLoopGroup bossGroup = new NioEventLoopGroup(1);        EventLoopGroup worker = new NioEventLoopGroup();        try{            ServerBootstrap b = new ServerBootstrap();            b.group(bossGroup, worker)                    .channel(NioServerSocketChannel.class)                    .option(ChannelOption.SO_BACKLOG, 100)                    .handler(new LoggingHandler(LogLevel.INFO))                    .childHandler(new ChannelInitializer<SocketChannel>() {                        @Override                        protected void initChannel(SocketChannel socketChannel) throws Exception {                            ChannelPipeline pipeline = socketChannel.pipeline();                            pipeline.addLast(                                    new ObjectEncoder(),                                    new ObjectDecoder(ClassResolvers.cacheDisabled(null)),                                    new EchoServerHandler());                        }                    });            ChannelFuture f = b.bind(PORT).sync();            f.channel().closeFuture().sync();        }catch (InterruptedException ie){            ie.printStackTrace();        }finally {            bossGroup.shutdownGracefully();            worker.shutdownGracefully();        }    }}

EchoServerHandler代码如下:

package com.leel0330.netty.echo;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;public class EchoServerHandler extends ChannelInboundHandlerAdapter{    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        System.out.println("read " + msg);        ctx.write("Echo: Hello Netty");    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {        ctx.flush();    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        cause.printStackTrace();        ctx.close();    }}

客户端EchoClient的代码如下:

package com.leel0330.netty.echo;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;import io.netty.handler.codec.serialization.ClassResolvers;import io.netty.handler.codec.serialization.ObjectDecoder;import io.netty.handler.codec.serialization.ObjectEncoder;public class EchoClient {    public static void main(String[] args){        final String HOST = "localhost";        final int PORT = 6666;        EventLoopGroup group = new NioEventLoopGroup();        try{            Bootstrap b = new Bootstrap();            b.group(group)                    .channel(NioSocketChannel.class)                    .option(ChannelOption.TCP_NODELAY, true)                    .handler(new ChannelInitializer<SocketChannel>() {                        @Override                        protected void initChannel(SocketChannel socketChannel) throws Exception {                            ChannelPipeline pipeline = socketChannel.pipeline();                            pipeline.addLast(                                    new ObjectEncoder(),                                    new ObjectDecoder(ClassResolvers.cacheDisabled(null)),                                    new EchoClientHandler());                        }                    });            ChannelFuture f = b.connect(HOST, PORT).sync();            f.channel().closeFuture().sync();        }catch (InterruptedException ie){            ie.printStackTrace();        }finally {            group.shutdownGracefully();        }    }}

EchoClientHandler代码如下:

package com.leel0330.netty.echo;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInboundHandlerAdapter;public class EchoClientHandler extends ChannelInboundHandlerAdapter{    @Override    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {        System.out.println("read " + msg);    }    @Override    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {    }    @Override    public void channelActive(ChannelHandlerContext ctx) throws Exception {        System.out.println("connect to server.");        ctx.writeAndFlush("Hello Netty");    }    @Override    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {        cause.printStackTrace();        ctx.close();    }}

2.2 一些重要类的说明

  • NioEventLoopGroup

    是一个多线程的处理IO操作的时间循环。在服务端程序,我们使用了2个,一个叫boss,用来处理客户端的连接,另一个叫worker,一旦客户端与服务端连接,worker便开始于客户端进行通信。在客户端我们只需要一个事件循环。

  • ServerBootstrap

    帮助你初始化Server的类,你也可以使用Channel,但是初始化过程会又长又无聊o(╯□╰)o。

  • Bootstrap

    类似ServerBootstrap,帮助你初始化Client的类。

  • NioServerSocketChannel

    初始化接受客户端连接的Channel。

  • SocketChannel

    在服务端,一旦客户端与服务端建立连接,需要使用SocketChannel与客户端的SocketChannel进行全双工通信。

  • ChannelPipeline

    Channel管道流,可以向其中添加需要Handler,比如编解码、处理读写事件等等,因为随着程序变得复杂,你很可能添加一些自定义的Handler来处理通信相关的问题。

  • ChannelFuture

    异步Channel IO操作的结果,在Netty中,所有的IO操作都是异步的,IO调用会立刻返回,ChannelFuture是uncompleted或者completed。当IO操作开始的时候,一个新的future被创建,初始化是uncompleted,如果IO操作结束成功、失败或者被取消,future被标记completed。

  • ChannelOption

    一些Socket相关的配置选项,如TCP_NODELAY、SO_BACKLOG等。

原创粉丝点击