[编织消息框架][设计协议]解决粘包半包(上)

理论部分

网络传输是以流的方式传送,这时会出现意想不到的事

如:发送两个消息 共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     }
原文地址:https://www.cnblogs.com/solq111/p/6535112.html