[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}

結果就是上面的樣子,解出來就可以去用了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM