Pigeon源码分析 -- 服务端解码消息格式
本文简单分析下pigeon请求的消息格式
先看一个类 com.dianping.pigeon.remoting.netty.codec.FrameDecoder
@Override protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception { Object message = null; if (buffer.readableBytes() <= 2) { return message; } byte[] headMsgs = new byte[2]; buffer.getBytes(buffer.readerIndex(), headMsgs); if ((0x39 == headMsgs[0] && 0x3A == headMsgs[1])) { //old protocol message = doDecode(buffer); } else if ((byte) 0xAB == headMsgs[0] && (byte) 0xBA == headMsgs[1]) { //new protocol message = _doDecode(buffer); } else { throw new IllegalArgumentException("Decode invalid message head:" + headMsgs[0] + " " + headMsgs[1] + ", " + "message:" + buffer); } return message; }
我们这里看新协议
protected Object _doDecode(ChannelBuffer buffer) throws Exception { CodecEvent codecEvent = null; if (buffer.readableBytes() <= CodecConstants._FRONT_LENGTH) {//这个buffer长度比真正消息体前的字节数还少,那就别读了 return codecEvent; } int totalLength = (int) (buffer.getUnsignedInt( buffer.readerIndex() + CodecConstants._HEAD_LENGTH));//这里正好说明头部四个字节之后的4个字节正是表示真正的消息体长度 int frameLength = totalLength + CodecConstants._FRONT_LENGTH_;
//public static final int _FRONT_LENGTH_ = _HEAD_LENGTH + _TOTAL_FIELD_LENGTH;//4 + 4
//frameLength表示消息头加消息体长度
if (buffer.readableBytes() >= frameLength) { ChannelBuffer frame = buffer.slice(buffer.readerIndex(), frameLength); buffer.readerIndex(buffer.readerIndex() + frameLength); codecEvent = new CodecEvent(frame, true); codecEvent.setReceiveTime(System.currentTimeMillis()); } return codecEvent; }
第二个4个字节表示的是消息体的长度,这里要注意消息体中前2个字节是请求头,而不是真实的请求数据。
第一个4个字节表示的东西很多
第1-2个字节固定为十六进制的0xAB、0xBA,即十进制的171、186,或8位有符号整型的-85、-70,可以用来区分是默认协议还是统一协议。
第3个字节为协议版本,也可以称作command字节,会用来定义编解码的相关自定义行为,如压缩方式、数据校验方式等,具体command第8位表示是否需要进行校验数据完整性,第6、7位定义了是否进行压缩及具体的压缩方式。
第4个字节为序列化方式,一般为1。
第5~8个字节为消息体长度。
引用自 【Pigeon源码阅读】RPC底层通信实现原理(八)_总结沉淀-CSDN博客
总结:
像这样的设计协议,我看就挺好了,消息头四个字节固定,然后四个字节表示消息体长度,总长度是消息体长度 + 4 + 4