在 http://chenjunfei0617.iteye.com/blog/2244947中已经介绍了Netty自带的两种解码器,这一节为大家介绍一个Netty自带的一种分隔符解码器DelimiterBasedFrameDecoder。分隔符解码器顾名思义就是完成以分隔符作为结束标志的消息的解码。
二:分隔符解码器的应用
本节以Echo服务为例,为大家介绍分隔符解码器的应用。
1、EchoServer
import io.netty.bootstrap.ServerBootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; 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; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; /** * 分隔符解码器的实现 * * @author chenjf * */ public class EchoServer { 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, 100)// .handler(new // LoggerHandler()) .childHandler(new ChannelInitializer<SocketChannel>() { protected void initChannel(SocketChannel cp) throws Exception { ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); cp.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); cp.pipeline().addLast(new StringDecoder()); cp.pipeline().addLast(new EchoServerHandler()); }; }); 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 EchoServer().bind(8080); } }
2、EchoServerHandler
import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; public class EchoServerHandler extends ChannelHandlerAdapter { private int count = 0; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // TODO Auto-generated method stub String body = (String) msg; System.out.println("this is " + ++count + " times receive client :" + body); body += "$_"; ByteBuf echo = Unpooled.copiedBuffer(body.getBytes()); ctx.writeAndFlush(echo); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // TODO Auto-generated method stub cause.printStackTrace(); ctx.close(); } }
3、EchoClient
import io.netty.bootstrap.Bootstrap; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; 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; import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.string.StringDecoder; public class EchoClient { 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 { ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); s.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, delimiter)); s.pipeline().addLast(new StringDecoder()); s.pipeline().addLast(new EchoClienHandler()); }; }); 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 EchoClient().connect("localhost", 8080); } }
4、EchoClienHandler
import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerAdapter; import io.netty.channel.ChannelHandlerContext; public class EchoClienHandler extends ChannelHandlerAdapter { private int count = 0; public static final String req = "hello,welcome to netty.$_"; public EchoClienHandler() { } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub for (int i = 0; i < 10; i++) { ctx.writeAndFlush(Unpooled.copiedBuffer(req.getBytes())); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // TODO Auto-generated method stub System.out.println("this is " + ++count + " times receive server :" + msg); } @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(); } }
运行结果如下:
服务器端:
this is 1 times receive client :hello,welcome to netty.
this is 2 times receive client :hello,welcome to netty.
this is 3 times receive client :hello,welcome to netty.
this is 4 times receive client :hello,welcome to netty.
this is 5 times receive client :hello,welcome to netty.
this is 6 times receive client :hello,welcome to netty.
this is 7 times receive client :hello,welcome to netty.
this is 8 times receive client :hello,welcome to netty.
this is 9 times receive client :hello,welcome to netty.
this is 10 times receive client :hello,welcome to netty.
客户端:
this is 1 times receive server :hello,welcome to netty.
this is 2 times receive server :hello,welcome to netty.
this is 3 times receive server :hello,welcome to netty.
this is 4 times receive server :hello,welcome to netty.
this is 5 times receive server :hello,welcome to netty.
this is 6 times receive server :hello,welcome to netty.
this is 7 times receive server :hello,welcome to netty.
this is 8 times receive server :hello,welcome to netty.
this is 9 times receive server :hello,welcome to netty.
this is 10 times receive server :hello,welcome to netty.