-
Notifications
You must be signed in to change notification settings - Fork 0
/
编码解码器.txt
95 lines (87 loc) · 3.65 KB
/
编码解码器.txt
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
82
83
84
85
86
87
88
89
90
91
92
93
94
1、 编码器
public class ProtobufEncoder extends MessageToByteEncoder<ProtoMsg.Message> {
@Override
protected void encode(ChannelHandlerContext ctx, ProtoMsg.Message msg, ByteBuf out)
throws Exception {
byte[] bytes = msg.toByteArray();// 将对象转换为byte
int length = bytes.length;// 读取消息的长度
ByteBuf buf = Unpooled.buffer(2 + length);
buf.writeShort(length);// 先将消息长度写入,也就是消息头
buf.writeBytes(bytes);// 消息体中包含我们要发送的数据
out.writeBytes(buf);
}
}
2、解码器
public class ProtobufDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in,
List<Object> out) throws Exception {
// 标记一下当前的readIndex的位置
in.markReaderIndex();
// 判断包头长度
if (in.readableBytes() < 2) {// 不够包头
return;
}
// 读取传送过来的消息的长度。
int length = in.readUnsignedShort();
// 长度如果小于0
if (length < 0) {// 非法数据,关闭连接
ctx.close();
}
if (length > in.readableBytes()) {// 读到的消息体长度如果小于传送过来的消息长度
// 重置读取位置
in.resetReaderIndex();
return;
}
ByteBuf frame = Unpooled.buffer(length);
in.readBytes(frame);
try {
byte[] inByte = frame.array();
// 字节转成对象
ProtoMsg.Message msg = ProtoMsg.Message.parseFrom(inByte);
if (msg != null) {
// 获取业务消息头
out.add(msg);
}
} catch (Exception e) {
LOG.info(ctx.channel().remoteAddress() + ",decode failed.", e);
}
}
}
====================================================================================
1、编码器
@Override
protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) throws Exception {
byte[] body = convertToBytes(msg); //将对象转换为byte,伪代码,具体用什么进行序列化,你们自行选择。可以使用我上面说的一些
int dataLength = body.length; //读取消息的长度
out.writeInt(dataLength); //先将消息长度写入,也就是消息头
out.writeBytes(body); //消息体中包含我们要发送的数据
}
2、解码器
public void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) {
if (in.readableBytes() < HEAD_LENGTH) { //这个HEAD_LENGTH是我们用于表示头长度的字节数。 由于上面我们传的是一个int类型的值,所以这里HEAD_LENGTH的值为4.
return;
}
in.markReaderIndex(); //我们标记一下当前的readIndex的位置
int dataLength = in.readInt(); // 读取传送过来的消息的长度。ByteBuf 的readInt()方法会让他的readIndex增加4
if (dataLength < 0) { // 我们读到的消息体长度为0,这是不应该出现的情况,这里出现这情况,关闭连接。
ctx.close();
}
if (in.readableBytes() < dataLength) { //读到的消息体长度如果小于我们传送过来的消息长度,则resetReaderIndex. 这个配合markReaderIndex使用的。把readIndex重置到mark的地方
in.resetReaderIndex();
return;
}
byte[] body = new byte[dataLength]; // 嗯,这时候,我们读到的长度,满足我们的要求了,把传送过来的数据,取出来吧~~
in.readBytes(body); //
Object o = convertToObject(body); //将byte数据转化为我们需要的对象。伪代码,用什么序列化,自行选择
out.add(o);
}