当前位置: 首页 > wzjs >正文

国外做化工网站惠州市建设厅网站

国外做化工网站,惠州市建设厅网站,老网站改版,青岛注册公司流程2023年binary.LittleEndian 是 Go 语言 encoding/binary 包中的一个常量,用于指定字节序(Byte Order)。字节序是指多字节数据在内存中存储的顺序,有两种主要方式: 小端序(Little Endian):…

binary.LittleEndian 是 Go 语言 encoding/binary 包中的一个常量,用于指定字节序(Byte Order)。字节序是指多字节数据在内存中存储的顺序,有两种主要方式:

  • 小端序(Little Endian):低字节存于内存低地址,高字节存于高地址。例如,整数 0x12345678 在小端序中存储为 78 56 34 12
  • 大端序(Big Endian):高字节存于内存低地址,低字节存于高地址。同样的整数 0x12345678 在大端序中存储为 12 34 56 78

encoding/binary 包概述

encoding/binary 包提供了字节序相关的编码和解码功能,常用于网络协议、文件格式或其他二进制数据的处理。主要功能包括:

  1. 字节序常量

    • binary.LittleEndian:小端序
    • binary.BigEndian:大端序
    • binary.NativeEndian:系统原生字节序(Go 1.19+)
  2. 核心函数

    • binary.Write(w io.Writer, order ByteOrder, data interface{}) error:将数据按指定字节序写入 io.Writer
    • binary.Read(r io.Reader, order ByteOrder, data interface{}) error:从 io.Reader 按指定字节序读取数据。
    • order.PutUint16/32/64(b []byte, v uint64):将整数按指定字节序写入字节切片。
    • order.Uint16/32/64(b []byte):从字节切片按指定字节序解析整数。

代码分析

if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetMsgId()); err != nil {return nil, err
}
  • dataBuff 是一个 io.Writer(如 bytes.Buffer),用于存储二进制数据。
  • binary.LittleEndian 指定使用小端序编码。
  • msg.GetMsgId() 返回一个整数(如 uint16),表示消息ID。

这段代码的作用是将消息ID按小端序写入 dataBuff。例如,如果 msg.GetMsgId() 返回 0x1234,则在 dataBuff 中存储为 34 12

选择字节序的建议

  • 网络协议:通常使用大端序(如 TCP/IP 协议)。
  • 文件格式:取决于具体规范(如 PNG 使用大端序,Windows PE 文件使用小端序)。
  • 系统内部:建议与平台原生字节序一致(可用 binary.NativeEndian)。

示例代码

下面是一个简单示例,展示如何使用 binary.Writebinary.Read

package mainimport ("bytes""encoding/binary""fmt"
)func main() {// 创建一个缓冲区var buf bytes.Buffer// 写入一个 uint32 整数(值为 0x12345678),使用小端序err := binary.Write(&buf, binary.LittleEndian, uint32(0x12345678))if err != nil {fmt.Println("写入错误:", err)return}// 输出缓冲区内容(小端序:78 56 34 12)fmt.Printf("小端序编码结果: %x\n", buf.Bytes())// 重置缓冲区以读取数据buf.Reset()buf.Write([]byte{0x78, 0x56, 0x34, 0x12}) // 手动写入小端序数据// 读取并解析为 uint32var result uint32err = binary.Read(&buf, binary.LittleEndian, &result)if err != nil {fmt.Println("读取错误:", err)return}fmt.Printf("解析结果: 0x%x\n", result) // 输出: 0x12345678
}

输出结果:

小端序编码结果: 78563412
解析结果: 0x12345678

这个示例展示了如何使用 binary.Write 将整数按小端序编码,以及如何使用 binary.Read 解码。如果将 binary.LittleEndian 替换为 binary.BigEndian,则编码结果会变为 12345678


TCP封包拆包案例

  • 为了解决自实现tcp读取时发生粘包问题,而封装长度字段来识别tcp数据长度,避免多读其他数据段

转自刘丹冰大佬 https://www.bilibili.com/video/BV1wE411d7th/?p=5

datapack.go

package znetimport ("bytes""encoding/binary""errors""zinx/utils""zinx/ziface"
)type IDataPack interface{GetHeadLen() uint32					//获取包头长度方法Pack(msg IMessage)([]byte, error)	//封包方法Unpack([]byte)(IMessage, error)		//拆包方法
}type IMessage interface {GetDataLen() uint32	//获取消息数据段长度GetMsgId() uint32	//获取消息IDGetData() []byte	//获取消息内容SetMsgId(uint32)	//设计消息IDSetData([]byte)		//设计消息内容SetDataLen(uint32)	//设置消息数据段长度
}type Message struct {Id      uint32 //消息的IDDataLen uint32 //消息的长度Data    []byte //消息的内容
}// 封包拆包类实例,暂时不需要成员
type DataPack struct{}// 封包拆包实例初始化方法
func NewDataPack() *DataPack {return &DataPack{}
}// 获取包头长度方法
func (dp *DataPack) GetHeadLen() uint32 {//Id uint32(4字节) +  DataLen uint32(4字节)return 8
}// 封包方法(压缩数据)
func (dp *DataPack) Pack(msg ziface.IMessage) ([]byte, error) {//创建一个存放bytes字节的缓冲dataBuff := bytes.NewBuffer([]byte{})//写msgIDif err := binary.Write(dataBuff, binary.LittleEndian, msg.GetMsgId()); err != nil {return nil, err}//写dataLenif err := binary.Write(dataBuff, binary.LittleEndian, msg.GetDataLen()); err != nil {return nil, err}//写data数据if err := binary.Write(dataBuff, binary.LittleEndian, msg.GetData()); err != nil {return nil, err}return dataBuff.Bytes(), nil
}// 拆包方法(解压数据)
func (dp *DataPack) Unpack(binaryData []byte) (ziface.IMessage, error) {//创建一个从输入二进制数据的ioReaderdataBuff := bytes.NewReader(binaryData)//只解压head的信息,得到dataLen和msgIDmsg := &Message{}//读msgIDif err := binary.Read(dataBuff, binary.LittleEndian, &msg.Id); err != nil {return nil, err}//读dataLenif err := binary.Read(dataBuff, binary.LittleEndian, &msg.DataLen); err != nil {return nil, err}//判断dataLen的长度是否超出我们允许的最大包长度if utils.GlobalObject.MaxPacketSize > 0 && msg.DataLen > utils.GlobalObject.MaxPacketSize {return nil, errors.New("Too large msg data recieved")}//这里只需要把head的数据拆包出来就可以了,然后再通过head的长度,再从conn读取一次数据return msg, nil
}

datapack_test.go

package znetimport ("fmt""io""net""testing"
)//只是负责测试datapack拆包,封包功能
func TestDataPack(t *testing.T) {//创建socket TCP Serverlistener, err := net.Listen("tcp", "127.0.0.1:7777")if err != nil{fmt.Println("server listen err:", err)return}//创建服务器gotoutine,负责从客户端goroutine读取粘包的数据,然后进行解析go func (){for{conn, err := listener.Accept()if err != nil{fmt.Println("server accept err:", err)}//处理客户端请求go func(conn net.Conn){//创建封包拆包对象dpdp := NewDataPack()for{//1 先读出流中的head部分headData := make([]byte, dp.GetHeadLen())_, err := io.ReadFull(conn, headData)  //ReadFull 会把msg填充满为止if err != nil {fmt.Println("read head error")}//将headData字节流 拆包到msg中msgHead,err := dp.Unpack(headData)if err != nil{fmt.Println("server unpack err:", err)return}if msgHead.GetDataLen() > 0 {//msg 是有data数据的,需要再次读取data数据msg := msgHead.(*Message)	// 接口转具体类型msg.Data = make([]byte, msg.GetDataLen())//根据dataLen从io中读取字节流_, err := io.ReadFull(conn, msg.Data)if err != nil {fmt.Println("server unpack data err:", err)return}fmt.Println("==> Recv Msg: ID=", msg.Id, ", len=", msg.DataLen, ", data=", string(msg.Data))}}}(conn)}}()//客户端goroutine,负责模拟粘包的数据,然后进行发送conn, err := net.Dial("tcp", "127.0.0.1:7777")if err != nil{fmt.Println("client dial err:", err)return}//创建一个封包对象 dpdp := NewDataPack()//封装一个msg1包msg1 := &Message{Id:0,DataLen:5,Data:[]byte{'h', 'e', 'l', 'l', 'o'},}sendData1, err := dp.Pack(msg1)if err!= nil{fmt.Println("client pack msg1 err:", err)return}msg2 := &Message{Id:1,DataLen:7,Data:[]byte{'w', 'o', 'r', 'l', 'd', '!', '!'},}sendData2, err := dp.Pack(msg2)if err!= nil{fmt.Println("client temp msg2 err:", err)return}//将sendData1,和 sendData2 拼接一起,组成粘包sendData1 = append(sendData1, sendData2...)//向服务器端写数据conn.Write(sendData1)//客户端阻塞select{}
}

https://github.com/0voice


文章转载自:

http://XyH7v7MD.qcwck.cn
http://zRfrHELH.qcwck.cn
http://65YXFqWa.qcwck.cn
http://bFnQjbNT.qcwck.cn
http://zAeJH7aI.qcwck.cn
http://VqKzVD0e.qcwck.cn
http://UEQyLmNe.qcwck.cn
http://qHSPZSHv.qcwck.cn
http://jXTbyd3s.qcwck.cn
http://RNZWaP7C.qcwck.cn
http://0K5UPWsM.qcwck.cn
http://MTv94RvT.qcwck.cn
http://XyAgZd24.qcwck.cn
http://az82ZTai.qcwck.cn
http://CfUTQhYt.qcwck.cn
http://Ww39tp1E.qcwck.cn
http://yly74la3.qcwck.cn
http://uumGfYyW.qcwck.cn
http://zY3iF3Qu.qcwck.cn
http://BnEyQ4kZ.qcwck.cn
http://E4sZy0Y0.qcwck.cn
http://9QxwgWQ4.qcwck.cn
http://fraTk00L.qcwck.cn
http://T7oZyrUr.qcwck.cn
http://wA9J3zvI.qcwck.cn
http://4SUn8p5y.qcwck.cn
http://8dlJEZje.qcwck.cn
http://D0awam3H.qcwck.cn
http://gDUhPlpf.qcwck.cn
http://B2sZESDV.qcwck.cn
http://www.dtcms.com/wzjs/632844.html

相关文章:

  • 网站建设市场需求分析做运营需要知道素材网站
  • 百度搜索网站淘宝网店开店网站建设
  • 现在做个人网站管理咨询顾问是做什么的
  • 什么系统做购物网站好临汾网站开发
  • 石家庄网站建设模板网站所有页面只显示域名
  • 金华建站模板UE4做购物网站
  • 自营店网站建设html5移动网站制作
  • 网站建设培训哪里好网页游戏排行榜魔域
  • 网站备案单位的联系方式重庆中信建投期货有限公司
  • 沧州网站运营公司中国建设银行下载安装
  • 网站手机自适应cms网站后台模版
  • 自己网站如何做关键词排名阿里云服务器618
  • 在线网站软件免费下载安装贵 建设厅网站文件
  • 锛网站建设部资质网站查询
  • wordpress网站模板下载dede网站幻灯片
  • 有没有专业做淘宝网站吗外贸网络推广专员
  • 建设在线教育网站他达拉非的副作用和危害
  • 网站没有做适配 怎么办一起做网店类似网站
  • 网站用哪些系统做的比较好用seo最新教程
  • 有没有兼职做设计的网站吗三合一网站管理系统
  • 四平市城乡建设局网站自助建站免费建站平台
  • 长沙建设公司网站短视频运营公司
  • 顺的网站建设效果南昌专业做网站公司
  • 网站用哪些系统做的网店怎么运营推广
  • 国外php网站源码网站建设怎么添加背景音乐
  • 深圳网站建设美橙互联wordpress自己写界面
  • pc端网站做移动适配正规十大电商平台
  • vs做网站怎么添加子页外包制作app软件要多少钱
  • 网站更换主机需要怎么做深圳乐创网站建设
  • 网页设计与网站建设 石油大学该网站无备案