package com.anyun.im_lib.netty; import com.anyun.im_lib.HeartbeatRespHandler; import com.anyun.im_lib.LoginAuthRespHandler; import com.anyun.im_lib.interf.IMSClientInteface; import io.netty.channel.Channel; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.handler.codec.FixedLengthFrameDecoder; import io.netty.handler.codec.LengthFieldBasedFrameDecoder; /** * MyApplication2 * channel初始化 * Created by lzw on 2019/12/2. 15:56:39 * 邮箱:632393724@qq.com * All Rights Saved! Chongqing AnYun Tech co. LTD */ public class TCPChannelInitializerHandler extends ChannelInitializer { private IMSClientInteface imsClient; public TCPChannelInitializerHandler(NettyTcpClient nettyTcpClient) { this.imsClient = nettyTcpClient; } @Override protected void initChannel(Channel channel) throws Exception { ChannelPipeline pipeline = channel.pipeline(); //netty提供的自定义长度解码器,解决TP拆包/粘包问题 // TODO: 2019/12/4 // (1) maxFrameLength - 发送的数据包最大长度; // //(2) lengthFieldOffset - 长度域偏移量,指的是长度域位于整个数据包字节数组中的下标; // //(3) lengthFieldLength - 长度域的自己的字节数长度。 // //(4) lengthAdjustment – 长度域的偏移量矫正。 如果长度域的值,除了包含有效数据域的长度外,还包含了其他域(如长度域自身)长度,那么,就需要进行矫正。矫正的值为:包长 - 长度域的值 – 长度域偏移 – 长度域长。 // //(5) initialBytesToStrip – 丢弃的起始字节数。丢弃处于有效数据前面的字节数量。比如前面有4个节点的长度域,则它的值为4。 // // 在上面的例子中,自定义长度解码器的构造参数值如下: // // LengthFieldBasedFrameDecoder spliter=new LengthFieldBasedFrameDecoder(1024,0,4,0,4); // 第一个参数为1024,表示数据包的最大长度为1024;第二个参数0,表示长度域的偏移量为0,也就是长度域放在了最前面,处于包的起始位置;第三个参数为4,表示长度域占用4个字节;第四个参数为0,表示长度域保存的值,仅仅为有效数据长度,不包含其他域(如长度域)的长度;第五个参数为4,表示最终的取到的目标数据包,抛弃最前面的4个字节数据,长度域的值被抛弃。 // // 为了更加清楚的说明一下上面的规则,调整一下例子中的代码。在写入通道前,在数据 // pipeline.addLast(new LengthFieldBasedFrameDecoder(1024,3 ,4,0,13)); pipeline.addLast(new FixedLengthFrameDecoder(10)); // 测试用 固定长度消息 //握手认证消息相应处理handler // pipeline.addLast(LoginAuthRespHandler.class.getSimpleName(), new LoginAuthRespHandler(imsClient)); //心跳消息响应处理handler // pipeline.addLast(HeartbeatRespHandler.class.getSimpleName(), new HeartbeatRespHandler(imsClient)); //接收消息处理handler pipeline.addLast(TCPReadHandler.class.getSimpleName(),new TCPReadHandler(imsClient)); } }