有谁精通netty ,数据包解码是,不确定数据包大小,怎么能收到完整的数据包?
我有个程序的包结构是这样的:1byte(包类型)+4byte(包体长度)+实际包体,于是写了下面的代码:
[code="java"]
public class ReceivingPacketHandler extends FrameDecoder {
public static fianl int HEADER_SIZE=5;
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel,
ChannelBuffer buf) throws Exception {
if (buf.readableBytes() < HEADER_SIZE) {
// The header length field was not received yet - return null.
return null;
}
buf.markReaderIndex();
// Read protocol header
buf.readByte();
// Read the data length field.
int length = buf.readInt();
buf.resetReaderIndex();
// Make sure if there's enough bytes in the buffer.
int totalLength = length + HEADER_SIZE;
if (buf.readableBytes() < totalLength) {
//the whole packet was not received yet - return null.
return null;
}
Packet recievedPacket = new Packet(size >= 0 ? size : bufSize);
recievedPacket.clear();
recievedPacket.readPacket(buf, totalLength);
return recievedPacket;
}
}
[/code]
这个和是否是netty没有关系,基于TCP的通信必须要有一定的规范,通常会在包头定义包的长度,你可以根据长度readFully读出整个包
这个跟是不是用netty没有关系,牵涉到网络通信的地方都需要进行协议的制定。一般来说有如下几个点:
1、结构定义:magicNumber+packageLength+自定义字段+消息内容+校验码
2、粘包处理:解包的时候,先查找magicNum的位置,然后开始读取包长度,解析出有用的消息内容。如果接受的数据不足以刚好解出完整个数的数据包,把剩余的数据放到缓存,等下次接受数据之后拼接起来继续解包。
把上面两个做好就可以了。
我写过一系列的文章,对netty的源码研究过,[url]http://asialee.iteye.com/blog/1769508[/url],不知道对lz会不会有帮助,其中的DelimiterBasedFrameDecoder、LengthFieldBasedFrameDecoder、FrameDecoder希望对lz有所帮助。
不确定包体的大小,可以采用header-content的方式,在header中标示真实包体的长度,类似http1.0协议中的content-length。具体可以参照netty中的objectencoder,首先长度位用4个字节占位待所有的内容写完再讲真实的长度写会长度占位