[Go] 輕量服務器框架tcp的粘包問題 封包與拆包

tcp傳輸的數據是以流的形式傳輸的,所以就沒有辦法判斷到哪裏結束算是本身的一個消息,這樣就會出現粘包問題,多個包粘在一塊兒了tcp

能夠使用這樣一個自定義的形式來解決,一個消息分爲 head+body  head包括數據的長度和數據編號 , 長度和編號都是uint32類型 也就是32位 佔有4個字節 , 總共head佔有8個字節測試

封裝一個消息的結構體,做爲一個數據實體,好比下面這個,編號 數據 數據長度  三個屬性ui

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
}

封裝一個封包解包的結構體,包括封包和解包的方法,封包就是先寫長度,再寫編號,再寫數據;解包只是獲取下長度和編號,數據下次再取spa

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
}

測試,先封包再解包code

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

結果就是上面的樣子,解出來就能夠去用了it

相關文章
相關標籤/搜索