解码器

Netty解码的艺术

瘦欲@ 提交于 2019-11-26 23:41:48
什么是拆包/粘包:   TCP 粘包/拆包:   TCP 是一个“流”协议,所谓流,就是没有界限的一长串二进制数据。TCP 作为传输层协议并不了解上层业务数据的具体含义,它会根据TCP 缓冲区的实际情况进行数据包的划分,所以在业务上认为是一个完整的包,可能会被TCP 拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这就是所谓的TCP 粘包和拆包问题。同样, 在Netty 的编码器中, 也会对半包和粘包问题做相应的处理。什么是半包, 顾名思义, 就是不完整的数据包, 因为netty 在轮询读事件的时候, 每次将channel 中读取的数据, 不一定是一个完整的数据包, 这种情况, 就叫半包。粘包同样也不难理解, 如果Client 往Server 发送数据包, 如果发送频繁很有可能会将多个数据包的数据都发送到通道中, 如果在server 在读取的时候可能会读取到超过一个完整数据包的长度, 这种情况叫粘包。有关半包和粘包, 如下图所示: 粘包问题的解决策略:   由于底层的TCP 无法理解上层的业务数据,所以在底层是无法保证数据包不被拆分和重组的,这个问题只能通过上层的应用协议栈设计来解决。业界的主流协议的解决方案,可以归纳如下: 消息定长,报文大小固定长度,例如每个报文的长度固定为200 字节,如果不够空位补空格; 包尾添加特殊分隔符

netty自定义解码器

隐身守侯 提交于 2019-11-26 22:39:18
在socket传输通信中容易丢包问题,什么半包问题,这些都是很正常的问题,处理方法就是定义自己的编解码规则了,让每次接收按定义好的规则为一个完整包作为数据源即可。 下面个例子就是netty自定义的一个解码器: 1 import io.netty.buffer.ByteBuf; 2 import io.netty.buffer.ByteBufAllocator; 3 import io.netty.channel.ChannelHandlerContext; 4 import io.netty.handler.codec.ByteToMessageDecoder; 5 import java.util.List; 6 7 public class XmlDecoder extends ByteToMessageDecoder { 8 9 String lastStr = ""; 10 11 @Override 12 protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { 13 System.out.println("解码器:"); 14 int len = in.readableBytes(); 15 if (len < 1) return;

LengthFieldBasedFrameDecoder

旧巷老猫 提交于 2019-11-25 18:58:50
原文链接: https://www.cnblogs.com/crazymakercircle/p/10294745.html 1.1.1. 解码器:FrameDecoder 前面所讲的解码器,在获取入站数据时,都是通过ByteBuf的基础类型读取方法,读取到是基础的数据类型,比如int整数。如果在解码时,读取的不是基础类型,而是非常基础的二进制数据,该如何处理呢? 大家都知道,TCP协议是个“流”性质协议,它的底层根据二进制缓冲区的实际情况进行包的划分,会把上层(Netty层)的ByteBuf包,进行重新的划分和重组,组成一帧一帧的二进制数据。换句话说,一个上层Netty中的 ByteBuf包,可能会被TCP底层拆分成多个二进制数据帧进行发送;也有可能,底层将多个小的ByteBuf包,封装成一个大的底层数据帧发送出去。 问题来了:如何从底层的二进制数据帧中,界定出来上层数据包的边界,也即是上层包的起点和末尾呢?别急,界定的办法,还是很多的。比如说,简单一点方法就是规定上层数据包的长度。例如,规定每个上层数据包的长度为100byte。再比如说,可以规定上层包的分割符号,比如换行符。无论采用什么方法,最为重要的是,发送方和接收方,在界定方法上必须保持一致。 Netty中,提供了几个重要的可以直接使用的帧解码器。这里先介绍一个最为基础的,它就是LineBasedFrameDecoder