• [Go] 轻量服务器框架tcp的粘包问题 封包与拆包


    tcp传输的数据是以流的形式传输的,因此就没有办法判断到哪里结束算是自己的一个消息,这样就会出现粘包问题,多个包粘在一起了

    可以使用这样一个自定义的形式来解决,一个消息分为 head+body  head包括数据的长度和数据编号 , 长度和编号都是uint32类型 也就是32位 占有4个字节 , 总共head占有8个字节

    封装一个消息的结构体,作为一个数据实体,比如下面这个,编号 数据 数据长度  三个属性

    package znet
    
    type Message struct {
        Id     uint32
        Data   []byte
        MsgLen uint32
    }
    
    func NewMessage() *Message {
        m := &Message{}
        return m
    }
    func (m *Message) GetId() uint32 {
        return m.Id
    }
    func (m *Message) GetData() []byte {
        return m.Data
    }
    func (m *Message) GetMsgLen() uint32 {
        return m.MsgLen
    }
    func (m *Message) SetId(id uint32) {
        m.Id = id
    }
    func (m *Message) SetData(data []byte) {
        m.Data = data
    }
    func (m *Message) SetMsgLen(len uint32) {
        m.MsgLen = len
    }

    封装一个封包解包的结构体,包括封包和解包的方法,封包就是先写长度,再写编号,再写数据;解包只是获取下长度和编号,数据下次再取

    package znet
    
    import "zinx/zinterface"
    
    import "bytes"
    
    import "encoding/binary"
    
    type DataPack struct {
    }
    
    func NewDataPack() *DataPack {
        dp := &DataPack{}
        return dp
    }
    func (dp *DataPack) Pack(m zinterface.IMessage) ([]byte, error) {
        dataBuff := bytes.NewBuffer([]byte{})
        binary.Write(dataBuff, binary.LittleEndian, m.GetMsgLen())
        binary.Write(dataBuff, binary.LittleEndian, m.GetId())
        binary.Write(dataBuff, binary.LittleEndian, m.GetData())
        return dataBuff.Bytes(), nil
    }
    func (dp *DataPack) Unpack(d []byte) (zinterface.IMessage, error) {
        m := NewMessage()
        r := bytes.NewReader(d)
        binary.Read(r, binary.LittleEndian, &m.MsgLen)
        binary.Read(r, binary.LittleEndian, &m.Id)
        return m, nil
    }

    测试,先封包再解包

        body:=[]byte("nihao")
        m:=znet.NewMessage()
        m.SetId(888)
        m.SetData(body)
        m.SetMsgLen(uint32(len(body)))
        log.Println(m)
    
        dp:=znet.NewDataPack()
        dataPack,_:=dp.Pack(m)
        log.Println(dataPack)
    
        m2,_:=dp.Unpack(dataPack)
        log.Println(m2)

    2019/12/17 15:42:30 &{888 [110 105 104 97 111] 5}
    2019/12/17 15:42:30 [5 0 0 0 120 3 0 0 110 105 104 97 111]
    2019/12/17 15:42:30 &{888 [] 5}

    结果就是上面的样子,解出来就可以去用了

  • 相关阅读:
    练习一
    Oracle删除一个库里面的所有表
    bat脚本中,@echo on与@echo off的使用
    bat命令之执行脚本后不退出窗口
    福清游玩
    MyEclipse快捷键
    过滤器与拦截器
    Anaconda-Jupyter的简单使用
    pycharm简单配置
    4、 vim&shell
  • 原文地址:https://www.cnblogs.com/taoshihan/p/12057619.html
Copyright © 2020-2023  润新知