[Go] 轻量服务器框架tcp的粘包问题 封包与拆包
程序员文章站
2022-06-23 22:54:27
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}
结果就是上面的样子,解出来就可以去用了
下一篇: 农村创业项目养殖业(4大养殖业项目推荐)