分隔符和定长解码器在netty中的应用
来源:互联网 发布:正规淘宝刷客平台 编辑:程序博客网 时间:2024/04/30 02:19
两种解码器:DelimiterBasedFrameDecoder和FixedLengthFrameDecoder
前者可以自动完成以分隔符做结束标志的消息的解码;
EchoClientHandler类:
分别启动服务端和客户端:服务端运行结果如下:
启动服务端,利用telnet命令进行测试EchoServer1服务端:
前者可以自动完成以分隔符做结束标志的消息的解码;
后者可以自动完成对定长消息的解码。
首先是分隔符解码器在netty中的应用,服务端:
public class EchoServer { public static void main(String[] args) { int port = 6767; if(args!=null&&args.length>0){ try { port = Integer.valueOf(args[0]); }catch (NumberFormatException e){ //采用默认值 } } new EchoServer().blind(port); } public void blind(int port){ EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); try{ ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup,workGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG,100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { //本例中使用"$_"作为分隔符 ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); /** * 创建DelimiterBasedFrameDecoder对象,它有多个构造方法; * 1024代表单条消息的最大长度,当达到该长度后任然没有找到分隔符, * 就抛出ToolLongFrameException异常; * 第二个参数就是分隔符缓冲对象 */ ch.pipeline().addLast(new DelimiterBasedFrameDecoder(1024,delimiter)); //将ByteBuf解码成字符串对象 ch.pipeline().addLast(new StringDecoder()); //EchoServerHandler接收到的msg消息就是解码后的字符串对象 ch.pipeline().addLast(new EchoServerHandler()); } }); //绑定端口,同步等待成功 ChannelFuture f = b.bind(port).sync(); //等待服务端监听端口关闭 f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { bossGroup.shutdownGracefully(); workGroup.shutdownGracefully(); } }}EchoServerHandler类:
public class EchoServerHandler extends ChannelHandlerAdapter{ int counter = 0; @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { /** * DelimiterBasedFrameDecoder自动请求消息进行了解码 * 后续的ChannelHandler接收到的msg对象就是个完整的消息包 */ String body = (String) msg; System.out.println("This is "+ ++counter+"times receive client :【"+ body+"】"); /** * 由于DelimiterBasedFrameDecoder过滤掉了分隔符, * 所以返回给客户端是需要在请求消息尾部拼接分隔符"$_" */ body += "$_"; ByteBuf echo = Unpooled.copiedBuffer(body.getBytes()); ctx.writeAndFlush(echo); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}客户端代码:
public class EchoClient { public static void main(String[] args) { int port = 6767; if(args!=null&&args.length>0){ try { port = Integer.valueOf(args[0]); }catch (NumberFormatException e){ //采用默认值 } } new EchoClient().connect(port,"127.0.0.1"); } public void connect(int port,String host){ //配置客户端NIO线程组 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 ch) throws Exception { ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes()); ch.pipeline().addLast( new DelimiterBasedFrameDecoder(1024,delimiter) ); ch.pipeline().addLast(new StringDecoder()); ch.pipeline().addLast(new EchoClientHandler()); } }); //发起异步连接操作 ChannelFuture f = b.connect(host,port).sync(); //等待客户端链路关闭 f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); }finally { group.shutdownGracefully();//优雅退出,释放NIO线程组 } }}
EchoClientHandler类:
public class EchoClientHandler extends ChannelHandlerAdapter{ private int counter; static final String ECHO_REQ = "Hi,LING. Welcome to Netty.$_"; public EchoClientHandler(){} @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { for(int i = 0;i<10;i++){ ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes())); } } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("This is "+ ++counter+"time receive server:["+msg+"]"); } @Override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}
分别启动服务端和客户端:服务端运行结果如下:
客户端运行结果:
即客户端发送了10条信息到服务端,并且服务端也接收到了客户端的10条信息,本例通过“$_”分割符,
用DelimiterBasedFrameDecoder对消息进行分割,没有出现粘包和拆包的现象。
定长解码器FixedLengthFrameDecoder在Netty中的应用:
服务端开发:
public class EchoServer1 { public static void main(String[] args) { int port = 6765; if(args!=null&&args.length>0){ try { port = Integer.valueOf(args[0]); }catch (NumberFormatException e){ //采用默认值 } } new EchoServer1().blind(port); } public void blind(int port){ //配置服务端的NIO线程组 NioEventLoopGroup bossGroup = new NioEventLoopGroup(); NioEventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup,workerGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.SO_BACKLOG,100) .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); p.addLast(new FixedLengthFrameDecoder(20)); //定长解码器,截取20个字节长度的请求消息 p.addLast(new StringDecoder()); p.addLast(new EchoServerHandler1()); } }); //绑定端口,同步等待成功 ChannelFuture f = b.bind(port).sync(); //等待服务端监听端口关闭 f.channel().closeFuture().sync(); } catch (InterruptedException e) { e.printStackTrace(); } }}EchoServerHandler1类:
public class EchoServerHandler1 extends ChannelHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { System.out.println("Receive client :["+msg+"]"); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close();//发生异常,关闭链路 }}
启动服务端,利用telnet命令进行测试EchoServer1服务端:
1.在【运行】菜单中输入cmd命令,打开命令行窗口;
2.在命令行输入“telnet localhost 6765”连接服务端;(和服务端端口对应)
3.输入命令行内容(需要开启本地回显才能看到输入的内容,我这里一直输入aaaa)
服务端运行结果:
由于之前设置了截取20字节长度,所以这里有20个a
这就是FixedLengthFrameDecoder在netty中的应用。
阅读全文
0 0
- 分隔符和定长解码器在netty中的应用
- Netty分隔符解码器和定长解码器的应用方案
- Netty的分隔符和定长解码器应用
- Netty中分隔符和定长解码器的应用
- [netty]--分隔符解码器DelimiterBasedFrameDecoder和定长解码器FixedLengthFrameDecoder
- Netty权威指南之分隔符和定长解码器
- netty之分隔符和定长解码器解决之道
- Netty (四) 分隔符和定长解码器的使用
- 《netty权威指南》5分隔符和定长解码器的应用
- 七、分隔符和定长解码器的应用(1)
- 八、分隔符和定长解码器的应用(2)
- Netty权威指南 第2版学习笔记5——分隔符和定长解码器的应用
- netty分割符和定长解码器的应用
- Netty学习之旅(三)(分隔符和定长解码器)
- Netty的分隔符解码器的使用
- <netty权威指南>笔记-分隔符解码器处理半包问题
- Netty:解码器
- 视频解码器SAA7111在图像采集中的应用
- August
- selenium驱动浏览器IE、Chrome、FireFox
- 最佳加法表达式
- Runnable JAR file spring + mybatis 普通项目(非maven 非springboot)
- word2vec原理推导与代码分析
- 分隔符和定长解码器在netty中的应用
- Eclipse 中 SSH 项目搭建图文教程(三)
- Android文件合并时,打包出错
- POJ 3254 Corn Fields (状压dp)
- combox的change事件触发另一个combox下拉框显示数据清空
- ACM随笔 17.8.31
- www服务器
- C语言实现插入排序
- openstack中API调用源码分析