Go   发布时间:2022-04-09  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了golang -- 网络字节编解码(1)大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

在网络传输协议过程中,封包常见的方式一般是:
①头标识+数据头(类型/属性/数据长度)+数据体+尾标识 -->一般还需要转义
②固定长度 --> 编解码方便,浪费宽带
③通过结尾标识(eg.通过base64传输,以\0结束) -->编解码方便,浪费 宽带


下面是golang在编解码的常用手段

  • @H_618_19@解码
    首先需要把[]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
}
  • @H_618_19@编码
    解码的逆过程,把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)
}
}

大佬总结

以上是大佬教程为你收集整理的golang -- 网络字节编解码(1)全部内容,希望文章能够帮你解决golang -- 网络字节编解码(1)所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。