• netty: 解决粘包拆包: 分隔符DelimiterBasedFrameDecoder,定长消息FixedLengthFrameDecoder


    DelimiterBasedFrameDecoder 自定义分隔符

    给Server发送多条信息,但是server会讲多条信息合并为一条。这时候我们需要对发生的消息指定分割,让client和server都知道这些消息是一条一条的

    //设置连接符/分隔符,换行显示
    ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
    //DelimiterBasedFrameDecoder:自定义分隔符
    sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
    				
    //设置为字符串形式的解码:将传递的buf改为String
    sc.pipeline().addLast(new  StringDecoder());
    	
    //处理消息			
    sc.pipeline().addLast(new ClientHandler());
    

      

    整体代码:

    public static void main(String[] args) throws InterruptedException {
    		
    		EventLoopGroup worker = new NioEventLoopGroup();
    		Bootstrap b = new Bootstrap();
    		b.group(worker)
    		.channel(NioSocketChannel.class)
    		.handler(new ChannelInitializer<SocketChannel>() {
    
    			@Override
    			protected void initChannel(SocketChannel sc) throws Exception {
    				// TODO Auto-generated method stub
    				//设置连接符/分隔符,换行显示
    				ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes());
    				//DelimiterBasedFrameDecoder:自定义分隔符
    				sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf));
    				
    				//设置为字符串形式的解码:将传递的buf改为String
    				sc.pipeline().addLast(new  StringDecoder());
    				
    				sc.pipeline().addLast(new ClientHandler());
    			}
    		});
    		//连接端口
    		ChannelFuture cf = b.connect("127.0.0.1", 8765).sync();
    		cf.channel().writeAndFlush(Unpooled.copiedBuffer("aaa$_".getBytes()));
    		cf.channel().writeAndFlush(Unpooled.copiedBuffer("bbbbb$_".getBytes()));
    		cf.channel().writeAndFlush(Unpooled.copiedBuffer("cccccccc$_".getBytes()));
    		
    		cf.channel().closeFuture().sync();		
    		worker.shutdownGracefully();
    		
    	}
    

      

    FixedLengthFrameDecoder 定长消息:及发送的消息需要一定的长度,当长度不够时,剩下的消息将会被丢弃,只能通过补空格来防止被丢弃

    //自定义长度,换行显示
    //设置每次发送长度为5个字符
    sc.pipeline().addLast(new FixedLengthFrameDecoder(5));
    				
    //设置为字符串形式的解码:将传递的buf改为String
    sc.pipeline().addLast(new  StringDecoder());
    	
    //处理消息			
    sc.pipeline().addLast(new ClientHandler());
    

      

    完整代码

    public static void main(String[] args) throws InterruptedException {
    		
    		EventLoopGroup worker = new NioEventLoopGroup();
    		Bootstrap b = new Bootstrap();
    		b.group(worker)
    		.channel(NioSocketChannel.class)
    		.handler(new ChannelInitializer<SocketChannel>() {
    
    			@Override
    			protected void initChannel(SocketChannel sc) throws Exception {
    				// TODO Auto-generated method stub
    				//设置定长长度为5个字符,换行显示		
                                    //每次发送消息的长度需要是5的倍数	
    				sc.pipeline().addLast(new FixedLengthFrameDecoder(5));
    				
    				//设置为字符串形式的解码:将传递的buf改为String
    				sc.pipeline().addLast(new  StringDecoder());
    				
    				sc.pipeline().addLast(new ClientHandler());
    			}
    		});
    		//连接端口
    		ChannelFuture cf = b.connect("127.0.0.1", 8765).sync();
    		
    //打印为:aaaaa
    //打印为:bb被丢弃,未满5个长度
    cf.channel().writeAndFlush(Unpooled.copiedBuffer("aaaaabb".getBytes()));
    		
    //打印为:bbbbb
    //打印完:ccccc
    cf.channel().writeAndFlush(Unpooled.copiedBuffer("bbbbbccccc".getBytes()));
    
    //打印为:ddddd
    //打印完:dd空格空格空格
    cf.channel().writeAndFlush(Unpooled.copiedBuffer("ddddddd 
      ".getBytes()));
    		
    		cf.channel().closeFuture().sync();		
    		worker.shutdownGracefully();
    		
    	}
    

      

  • 相关阅读:
    白话LINQ系列2以代码演进方式学习LINQ必备条件
    《Entity Framework 6 Recipes》中文翻译系列 (9) 第二章 实体数据建模基础之继承关系映射TPH
    Linq To Sqlite 一一二二
    《Entity Framework 6 Recipes》中文翻译系列 (10) 第二章 实体数据建模基础之两实体间Isa和Hasa关系建模、嵌入值映射
    《Entity Framework 6 Recipes》中文翻译系列 (14) 第三章 查询之查询中设置默认值和存储过程返回多结果集
    《Entity Framework 6 Recipes》中文翻译系列 (13) 第三章 查询之使用Entity SQL
    白话LINQ系列1什么是LINQ?
    《Entity Framework 6 Recipes》翻译系列 (3) 第二章 实体数据建模基础之创建一个简单的模型
    JS 实现trim()
    mysql表切换引擎的几种方法
  • 原文地址:https://www.cnblogs.com/achengmu/p/10944565.html
Copyright © 2020-2023  润新知