2016-04-05 20:45:51.0|分类: netty|浏览量: 2123
客户端和服务器端建立连接后,客户端向服务器端发送业务请求。服务器端收到请求,首先要对这个数据流进行解码,翻译成服务器端能识别的信息,这就是解码过程。解码(Decode)/反序列化(deserialization)把从网络、磁盘等读取的字节数组还原成原始对象。 编码它将对象序列化为字节数组,用于网络传输、数据持久化等用途。 常见的解码方法有:(1)LineBasedFrameDecoder是回车换行解码器,如果用户发送的消息以回车换行符作为消息结束的标识。(2)DelimiterBasedFrameDecoder是分隔符解码器,用户可以指定消息结束的分隔符,它可以自动完成以分隔符作为码流结束标识的消息的解码。回车换行解码器实际上是一种特殊的DelimiterBasedFrameDecoder解码器。(3)DelimiterBasedFrameDecoder是分隔符解码器,用户可以指定消息结束的分隔符,它可以自动完成以分隔符作为码流结束标识的消息的解码。回车换行解码器实际上是一种特殊的DelimiterBasedFrameDecoder解码器。还有LengthFieldBasedFrameDecoder等等。 常见的解包方式有很多种,都有各自的优缺点,根据自己的业务场景进行适当优化解包规则。TCP底层存在粘包和拆包,当我们在接受消息的时候,不能简单认为报文就是整个包消息。怎么知道这个包大小呢?假如我们有一个tag标示整个包的大小,数据到来之后我们解析这个tag得到包的大小,然后开始接受等大小的包。 数据通过在协议头/消息头中设置长度字段来标识整包消息。结构如下图: 定义了包的基本信息,包协议包括基本协议和包内容。包基本协议有:包大小:4个字节,标识这个业务包的总长度,比如这包大小解析值是1024K,收到的第一个包实际大小是900K,也就是说业务信息被拆成了2个包发送过来,解析完第一包,自动继续解析第二个数据包。 包类型:标识这个业务包的类型,代表是登陆、聊天、地图定位等等。 版本:标识程序版本号 信息方向:客户端向服务器发送包是cts,服务器向客户端发送消息是stc. 命令:具体业务操作指令,增删改查等操作。 通知类型 时间 发送方大小:业务包发送信息用户的身份识别大小,比如张三的id是10000,发送方大小值就是10000的数据大小。 接收方大小:业务包接受用户的身份识别大小,比如张三的id是10000,发送方大小值就是10000的数据大小。 基本协议数据的大小是22个byte,这个基本协议大小不会改变。包发送方内容、包接收方内容、消息内容大小都是不控制的。我们通过发送方大小、接收方大小控制发送方内容、包接收方内容接受。通过这个包的整体大小、协议栈大小、发送方大小、接收方大小控制内容接受。具体算法如下图: 实现代码: public class NettyMessageDecoder extends ByteToMessageDecoder { @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { int length = msg.readInt();//数据包总长度 //web请求,直接过滤 if(length == 1195725856){ // ioSession.close(true); return; } //in 转换成对象 ... 具体代码因为保密原因不能贴出来 } }
|