七叶笔记 » golang编程 » Golang 二进制协议 (Binary protocol) 理解应用

Golang 二进制协议 (Binary protocol) 理解应用

概述: 二进制协议 ( binary protocol) 高效地在底层处理数据通信,字节序决定字节输出的顺序、通过可变长度编码压缩数据存储空间。

字节序理解:

字节序:字节在电脑中存放时的序列与输入时的序列是先到的在前还是后到的在前。

字节序分为:

网络字节序 (Big Endian) 将高序字节存储在起始地址,俗称大端,网络传输和文件存储使用大端序。

主机字节序 (Littlr Endian) 将低序字节存储在起始地址,俗称小端,小端序应用于 CPU 内部存储数据;

注意:使用大端或者小端就好像有的人吃鸡蛋喜欢从大端那头打破鸡蛋,有的人喜欢从小端打破,就是这样。没有利弊,统一就好。

固定长度的数字写入字节切片 ( byte slice)

// write

v := uint32(500)

buf := make([]byte, 4)

binary.BigEndian.PutUint32(buf, v)

// read

x := binary.BigEndian.Uint32(buf)

流处理:

//Read 通过指定类型的字节序把字节解码 (decode) 到 data 变量中。

Read() func Read(r io.Reader, order ByteOrder, data interface{}) error

示例:read

import (

bytes

encoding /binary”

“fmt”

)

func main() {

var(

piVar float64

boolVar bool

)

piByte := []byte{0x18, 0x2d, 0x44, 0x54, 0xfb, 0x21, 0x09, 0x40}

boolByte := []byte{0x00}

piBuffer := bytes.NewReader( pi Byte)

boolBuffer := bytes.NewReader(boolByte)

binary.Read(piBuffer, binary.LittleEndian, &piVar)

binary.Read(boolBuffer, binary.LittleEndian, & boolByte)

fmt.Println(“pi”, piVar) // pi 3.141592653589793

fmt.Println(“bool”, boolVar) // bool false

}

//Write 通过指定类型的字节序把字节编码 (encode) 到 data 变量中。

Write() func Write(w io.Writer, order ByteOrder, data interface{}) error

示例:write

import (

“bytes”

“encoding/binary”

“fmt”

“math”

)

func main() {

buf := new(bytes.Buffer)

var pi float64 = math.Pi

err := binary.Write(buf, binary.LittleEndian, pi)

if err != nil {

fmt.Println(“binary.Write failed:”, err)

}

fmt.Printf(“% x”, buf.Bytes()) // 18 2d 44 54 fb 21 09 40

}

其它函数:

把可变长值写到内存字节切片中

func PutVarint(buf []byte, x int64) int

func PutUvarint(buf []byte, x uint64) int

函数 Varint() 和 Uvarint() 把字节码转为十进制。

func Varint(buf []byte) (int64, int)

func Uvarint(buf []byte) (uint64, int)

binary 包提供了两个函数从字节流中读取到可变长度值。

func ReadVarint(r io.ByteReader) (int64, error)

func ReadUvarint(r io.ByteReader) (uint64, error)

综合示例:编码解码

package main

import (

“fmt”

“bytes”

“encoding/binary”

)

// 二进制打包

func encode(vs …interface{}) []byte {

buf := new(bytes.Buffer)

for i := 0; i < len(vs); i++ {

binary.Write(buf, binary.LittleEndian, vs[i])

}

return buf.Bytes()

}

// 二进制解包,必须传入变量的地址

func decode(b []byte, vs …interface{}) {

buf := bytes.NewBuffer(b)

for i := 0; i < len(vs); i++ {

binary.Read(buf, binary.LittleEndian, vs[i])

}

}

func main() {

var i1 int32 = 1

var i2 int32 = 2

var i3 int32 = 3

var i4, i5, i6 int32

b := encode(i1, i2, i3)

fmt.Println(b)

decode(b, &i4, &i5, &i6)

fmt.Println(i4, i5, i6)

}

更多内容关注每日编程,每天进步一点。

相关文章