Netty是目前最流行的NIO框架之一,它的健壮性、功能、性能、可定制性和扩展性在同类框架中都是首屈一指的,目前流行的Hadoop的RPC框架avro使用Netty作为底层通信框架,它的主要优点有:
1、开发门槛低;
2、功能强大,支持多种主流协议;
3、性能高,成熟稳定;
4、定制能力强。
二:Netty入门应用
本节以时间服务器为例进行开发,客户端发送一个命令请求,服务器端接受命令返回当前日期给客户端,本节主要包括的内容有:
1、环境搭建
2、服务器端开发
3、客户端开发
4、测试
1、环境搭建:
可以通过maven来构建,也可以直接将netty的jar包导入到classpath中。
maven构建:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>5.0.0.Alpha2</version>
</dependency>
jar包方式:到官网 http://netty.io/downloads.html下载相应的开发包,解压,将\%nettyhome%\jar\all-in-one\目录下的jar导入到classpath即可
2、服务器端开发
TimeServer:时间服务器
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 TimeServer { public void bind(int port) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG, 1024).childHandler(new ChildChannelHandler()); ChannelFuture f = bootstrap.bind(port).sync(); f.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) { new TimeServer().bind(8080); } } class ChildChannelHandler extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel arg0) throws Exception { // TODO Auto-generated method stub arg0.pipeline().addLast(new TimeServerHandler()); } }
TimeServerHandler:时间服务端处理器
import java.util.Date; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; public class TimeServerHandler extends ChannelHandlerAdapter{ @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // TODO Auto-generated method stub ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req, "UTF-8"); System.out.println("the time server receive order :" + body); String currentyTime = "QUERY TIME ORDER".equalsIgnoreCase(body)?new Date(System.currentTimeMillis()).toString():"BAD ORDER"; ByteBuf copiedBuffer = Unpooled.copiedBuffer(currentyTime.getBytes()); ctx.write(copiedBuffer); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub ctx.close(); } }
3、客户端开发
TimeClient:客户端
import io.netty.bootstrap.Bootstrap; 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.NioSocketChannel; public class TimeClient { public void connect(String host,int port){ EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group).channel(NioSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true).handler(new ChannelInitializer<SocketChannel>() { protected void initChannel(SocketChannel s) throws Exception { s.pipeline().addLast(new TimeClienHandler()); }; }); ChannelFuture f = bootstrap.connect(host, port).sync(); f.channel().closeFuture().sync(); } catch (Exception e) { // TODO: handle exception } finally { group.shutdownGracefully(); } } public static void main(String[] args) { new TimeClient().connect("127.0.0.1", 8080); } }
TimeClienHandler:时间客户端处理器
import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; public class TimeClienHandler extends ChannelHandlerAdapter { private final ByteBuf buf; public TimeClienHandler() { byte[] req = "QUERY TIME ORDER".getBytes(); buf = Unpooled.buffer(req.length); buf.writeBytes(req); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub ctx.writeAndFlush(buf); } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // TODO Auto-generated method stub ByteBuf buf = (ByteBuf) msg; byte[] req = new byte[buf.readableBytes()]; buf.readBytes(req); String body = new String(req, "UTF-8"); System.out.println("now is :" + body); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub ctx.close(); } }
4、测试
先运行服务器TimeServer,然后运行TimeClient
服务器端收到:
the time server receive order :QUERY TIME ORDER
客户端收到:
now is :Fri Sep 18 10:05:36 CST 2015