lizhanwei
2020-02-18 87ab0bd072bd42c09a649759090942781ab53fcb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
package com.anyun.im_lib.netty;
 
import android.util.Log;
 
import com.anyun.im_lib.HeartbeatRespHandler;
import com.anyun.im_lib.LoginAuthRespHandler;
import com.anyun.im_lib.interf.IMSClientInteface;
 
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
 
 
/**
 * 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<Channel> {
 
    private static final String TAG = TCPChannelInitializerHandler.class.getSimpleName();
 
    private IMSClientInteface imsClient;
 
    public TCPChannelInitializerHandler(NettyTcpClient nettyTcpClient) {
        this.imsClient = nettyTcpClient;
    }
 
    @Override
    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        Log.i(TAG, "initChannel: ");
 
        //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 ,2,1,0));
 
//        pipeline.addLast(new FixedLengthFrameDecoder(10));  // 测试用  固定长度消息
 
//        pipeline.addLast(new LineBasedFrameDecoder(1024));
 
        byte[] bytes = new byte[]{0x7e};
        ByteBuf byteBuf = Unpooled.copiedBuffer(bytes);
        pipeline.addLast(new DelimiterBasedFrameDecoder(1024,byteBuf));
 
        //握手认证消息相应处理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));
    }
}