DelimiterBasedFrameDecoder分隔符解码器

发表时间:2017-10-26 13:54:28 浏览量( 36 ) 留言数( 0 )

学习目标:

1、了解DelimiterBasedFrameDecoder

2、能通过DelimiterBasedFrameDecoder编写代码


学习过程:

一、DelimiterBasedFrameDecoder介绍

    DelimiterBasedFrameDecoder分隔符解码器,用户可以指定消息结束的分隔符,它可以自动完成以分隔符作为码流结束标识的消息的解码。回车换行解码器实际上是一种特殊的DelimiterBasedFrameDecoder解码器。

二、示例代码

下面我们使用分隔符实现一个例子,分隔符可以自己定义的。

(1)自定义服务器端的Handler

public class DelimiterServerHandler extends ChannelInboundHandlerAdapter {
	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		
		String body=(String)msg;
		
		System.out.println("服务端收到的信息:"+body);
		
		String cuTime="Server Time:"+new Date()+"$#";
		
		ByteBuf resp=Unpooled.copiedBuffer(cuTime.getBytes());
		
		ctx.writeAndFlush(resp);
		
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}
}

(2)启动类

public class DelimiterServer {
	private int port;

	public DelimiterServer(int port) {
		this.port = port;
	}

	public void run() 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 {
							ByteBuf delimiter=Unpooled.copiedBuffer("$#".getBytes());
							ch.pipeline().addLast(new DelimiterBasedFrameDecoder(2048,delimiter),new StringDecoder(), new DelimiterServerHandler());
						}
					}).option(ChannelOption.SO_BACKLOG, 128) 
					.childOption(ChannelOption.SO_KEEPALIVE, true); 

			// 绑定端口,开始接收进来的连接
			ChannelFuture f = b.bind(port).sync(); 

			// 等待服务器 socket 关闭 。
			// 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。
			f.channel().closeFuture().sync();
		} finally {
			workerGroup.shutdownGracefully();
			bossGroup.shutdownGracefully();
		}
	}

	public static void main(String[] args) throws Exception {
		int port;
		if (args.length > 0) {
			port = Integer.parseInt(args[0]);
		} else {
			port = 8084;
		}
		new DelimiterServer(port).run();
	}

}

客户端代码

(1)自定义客户端的Handler

public class DelimiterClientHandler extends ChannelInboundHandlerAdapter {
	
	@Override
	public void channelActive(ChannelHandlerContext ctx) {
		
		System.out.println("LineClientHandler:channelActive");
		
		for(int i=0;i<100;i++) {
			String cuTime="client :"+i+"$#";
			ByteBuf resp=Unpooled.buffer(cuTime.getBytes().length);
			resp.writeBytes(cuTime.getBytes());
			ctx.writeAndFlush(resp);
		}
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		String body = (String) msg;

		System.out.println("客户端收到的信息:" + body);

	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}
}

(2)客户端启动类。

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

		String host ="localhost";
		int port = 8084;
		EventLoopGroup workerGroup = new NioEventLoopGroup();

		try {
			Bootstrap b = new Bootstrap(); 
			b.group(workerGroup); 
			b.channel(NioSocketChannel.class); 
			b.option(ChannelOption.SO_KEEPALIVE, true); 
			b.handler(new ChannelInitializer<SocketChannel>() {
				@Override
				public void initChannel(SocketChannel ch) throws Exception {
					ByteBuf delimiter=Unpooled.copiedBuffer("$#".getBytes());
					ch.pipeline().addLast(new DelimiterBasedFrameDecoder(2048,delimiter),new StringDecoder(),new DelimiterClientHandler());
				}
			});

			// 启动客户端
			ChannelFuture f = b.connect(host, port).sync(); // (5)

			// 等待连接关闭
			f.channel().closeFuture().sync();
		} finally {
			workerGroup.shutdownGracefully();
		}
	}
}

先启动服务端,在启动客户端,两边在接受数据时都没有发生错误。