欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-21 17:32:13
tcp传输的数据是以流的形式传输的,因此就没有办法判断到哪里结束算是自己的一个消息,这样就会出现粘包问题,多个包粘在一起了 可以使用这样一个自定义的形式来解决,一个消息分为 head+body head包括数据的长度和数据编号 , 长度和编号都是uint32类型 也就是32位 占有4个字节 , 总共 ......

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}

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