在网络传输协议过程中,封包常见的方式一般是:
①头标识+数据头(类型/属性/数据长度)+数据体+尾标识 -->一般还需要转义
②固定长度 --> 编解码方便,浪费宽带
③通过结尾标识(eg.通过base64传输,以\0结束) -->编解码方便,浪费 宽带
下面是golang在编解码的常用手段
解码
首先需要把[]byte的ascii串转化为uint8,uint16,uint32,uint64等 (分别对应python的B,H,I,Q).特别要注意大端和小端对齐方式(python大端">",小端"<",这里也用它们的ascii吧)
//这是一个例子,解码出">HHI" funcunpack(data[]byte,edianbyte)(uint16,[]byte){ dataType:=ToUInt16(data[0:2],edian) dataAttr:=ToUInt16(data[2:4],edian) dataLen:=ToUInt32(data[4:8],edian) extra:=data[8:] returndataType,dataAttr,dataLen,extra } funcToUInt8(buf[]byte,edianbyte)uint8{ //len(buf)==1-->B t:=uint8(buf[0]) returnt } funcToUInt16(buf[]byte,edianbyte)uint16{ //len(buf)==2-->H t:=uint16(buf[0]) ifedian==62{//">" t=t<<8|uint16(buf[1]) }elseifedian==60{//"<" t=t|uint16(buf[1])<<8 } returnt } funcToUInt32(buf[]byte,edianbyte)uint32{ //len(buf)==4-->I t:=uint32(buf[0]) ifedian==62{ t=t<<24 t=t|uint32(buf[1])<<16 t=t|uint32(buf[2])<<8 t=t|uint32(buf[3]) }elseifedian==60{ t=t|uint32(buf[1])<<8 t=t|uint32(buf[2])<<16 t=t|uint32(buf[3])<<24 } returnt } funcToUInt64(buf[]byte,edianbyte)uint64{ //len(buf)==8-->Q t:=uint64(buf[0]) ifedian==62{ t=t<<56 t=t|uint64(buf[1])<<48 t=t|uint64(buf[2])<<40 t=t|uint64(buf[3])<<32 t=t|uint64(buf[4])<<24 t=t|uint64(buf[5])<<16 t=t|uint64(buf[6])<<8 t=t|uint64(buf[7]) }elseifedian==60{ t=t|uint64(buf[1])<<8 t=t|uint64(buf[2])<<16 t=t|uint64(buf[3])<<24 t=t|uint64(buf[4])<<32 t=t|uint64(buf[5])<<40 t=t|uint64(buf[6])<<48 t=t|uint64(buf[7])<<56 } returnt }
编码
解码的逆过程,把uint8,uint32转化为[]byte -->ascii slice
//这是一个例子,编码为">HHI" funcpack(dataTypeuint16,dataAttruint16,dataLenuint32)[]byte{ buf:=make([]byte,8) PutUInt16(dataType,buf[0:2],62) PutUInt16(dataAttr,buf[2:4],62) PutUInt32(dataLen,buf[4:8],62) //buf=bufType+bufAttr+bufLen returnbuf } funcputUInt8(numuint8,buf[]byte,edianbyte){ //len(buf)==1 buf[0]=byte(num) } funcputUInt16(numuint16,edianbyte){ //len(buf)==2 buf[0]=byte(num>>8) buf[1]=byte(num) ifedian==62{//">" }elseifedian==60{//"<" buf[0]^=buf[1] buf[1]^=buf[0] buf[0]^=buf[1] } } funcputUInt32(numuint32,edianbyte){ //len(buf)==4 buf[0]=byte(num>>24) buf[1]=byte(num>>16) buf[2]=byte(num>>8) buf[3]=byte(num) ifedian==62{ }elseifedian==60{ buf[0]^=buf[3] buf[3]^=buf[0] buf[0]^=buf[3] buf[1]^=buf[2] buf[2]^=buf[1] buf[1]^=buf[2] } } funcputUInt64(numuint64,edianbyte){ //len(buf)==8 ifedian==62{ buf[0]=byte(num>>56) buf[1]=byte(num>>48) buf[2]=byte(num>>40) buf[3]=byte(num>>32) buf[4]=byte(num>>24) buf[5]=byte(num>>16) buf[6]=byte(num>>8) buf[7]=byte(num) }elseifedian==60{ buf[0]=byte(num) buf[1]=byte(num>>8) buf[2]=byte(num>>16) buf[3]=byte(num>>24) buf[4]=byte(num>>32) buf[5]=byte(num>>40) buf[6]=byte(num>>48) buf[7]=byte(num>>56) } }原文链接:https://www.f2er.com/go/191162.html