理论部分
网络传输是以流的方式传送,这时会出现意想不到的事
如:发送两个消息 共8byte
byte[] messagea=new byte[4];
byte[] messageb=new byte[4];
接收端: 可能会出现读两次或多次接收
解决粘包半包有很多方式
方式1.每条消息加结束标志:
如 byte[] endFlag = "messageEnd".getBytes();
messagea "+" endFlag
方式2.开头固定长度为消息:如先写消息长度(固定占多少byte),再写消息内容,读时先固定读长度,然后再积累内容
byte[] len = intToBytes(messagea.length);
len "+" messagea
方式1无法知道整条消息长度,而且每次接收都要与结束标志循环匹配,无法达到控制处理
方式2能优先知道消息长度,接下来无需再匹配处理,能控且简化处理逻辑
最终包传输以下面格式,有的长度为2或者1,有的没有校验,有的可能会加其它数据
内容长度-4 是因为写时加上校验的固定长度,读时要减去校验长度
源码解读
QPacket
1 public void writeToByteBuf(ByteBuf byteBuf) { 2 final int packetLen = toSize(); //计算包长度 3 byteBuf.writeShort(QMConfig.getInstance().getPacketHeadFlag(packetLen)); //写入包信息开头标志(2byte) 4 byteBuf.writeInt(packetLen); //写入包长度(4byte) 5 writeBytes(byteBuf);//写入内容 6 byteBuf.writeByte(QMConfig.getInstance().getPacketEndFlag(packetLen));//写入包信息结束标志(1byte) 7 } 8 9 public int writeBytes(ByteBuf byteBuf) { 10 byteBuf.writeLong(sn); //写入包序列 11 byteBuf.writeShort(c); //写入opCode 12 byteBuf.writeBytes(b); //写入消息内容 13 byteBuf.writeLong(sid); //写入会话标识 14 return toSize(); 15 }