[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()
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}
结果就是上面的样子,解出来就可以去用了
[Go] 轻量服务器框架tcp的粘包问题 封包与拆包的更多相关文章
- [Go] 轻量服务器框架基础TCP服务模块
框架要先把整体的结构定义好,一般都是在$GOPATH目录的src下建立自己的目录 zinterface是一些接口的定义 znet就是接口的具体实现 IServer.go package zinterf ...
- [Go] 轻量服务器框架基础TCP连接的抽象和封装
对tcp连接部分以及与连接绑定的业务部分进行抽象和封装 主要是对连接的开启关闭和读写进行封装,抽象出接口,使用回调进行具体业务的绑定 zinterface/iconnection.go package ...
- [Go] 轻量服务器框架全局配置的实现以及解析json
在一个应用中经常需要有一个配置文件,可以对代码中的参数进行配置,可以使用一个json文件来对应一个struct的对象,进行全局配置 建一个conf/zinx.json作为配置文件 { "Na ...
- 阿里云轻量服务器价格及轻量与ECS服务器区别比较
https://yq.aliyun.com/articles/221647 摘要: 阿里云轻量应用服务器价格表及介绍,关于轻量应用服务器和ECS服务器的性能对比 阿里云轻量应用服务器是阿里云新推出的服 ...
- TCP的粘包现象
看面经时,看到有面试官问TCP的粘包问题.想起来研一做购物车处理数据更新时遇到粘包问题,就总结一下吧. 1 什么是粘包现象 TCP粘包是指发送方发送的若干包数据到接收方接收时粘成一包,从接收缓冲区看, ...
- python 全栈开发,Day35(TCP协议 粘包现象 和解决方案)
一.TCP协议 粘包现象 和解决方案 黏包现象让我们基于tcp先制作一个远程执行命令的程序(命令ls -l ; lllllll ; pwd)执行远程命令的模块 需要用到模块subprocess sub ...
- TCP通信粘包问题分析和解决
转载至https://www.cnblogs.com/kex1n/p/6502002.html 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发 ...
- TCP通信粘包问题分析和解决(全)(转)
TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送 ...
- C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性
C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发 ...
随机推荐
- Geoserver2.15.1 配置自带 GeoWebCache 插件发布 ArcGIS Server 瓦片(附配置好的 Geoserver2.15.1 下载)
之前写过一篇关于 Geoserver2.8.5 版本的部署配置发布 ArcGIS Server 瓦片点击查看,那是下载 Geoserver2.8.5 源码编译,重新打包 jar 来部署配置思路的,版本 ...
- HDU1429
Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)…… 这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方.刚开 ...
- 【JS】325- 深度理解ES6中的解构赋值
点击上方"前端自习课"关注,学习起来~ 对象和数组时 Javascript 中最常用的两种数据结构,由于 JSON 数据格式的普及,二者已经成为 Javascript 语言中特别重 ...
- Vue单页面应用打包app处理返回按钮
情况 顶部返回,在header.vue公用组件中使用 this.$router.go(-1) 安卓:点击返回按钮:登录页,项目选择页,首页等几个一级页面要求提示用户是否退出app;确定,退出;取消:不 ...
- Spring与Shiro整合 加载权限表达式
Spring与Shiro整合 加载权限表达式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 如何加载权限表达式 我们在上章内容中画了一张图,里面有三个分项,用户 角色 权限: 那 ...
- CCF-CSP题解 201609-3 炉石传说
模拟. 注意随从的编号在\(summon\)和\(attack\)随从死亡时都可能改变. #include <bits/stdc++.h> using namespace std; str ...
- 《Java基础知识》Java 运算符
计算机的最基本用途之一就是执行数学运算,作为一门计算机语言,Java也提供了一套丰富的运算符来操纵变量.我们可以把运算符分成以下几组: 算术运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 其他运 ...
- Vue基础系列(五)——Vue中的指令(中)
写在前面的话: 文章是个人学习过程中的总结,为方便以后回头在学习. 文章中会参考官方文档和其他的一些文章,示例均为亲自编写和实践,若有写的不对的地方欢迎大家和我一起交流. VUE基础系列目录 < ...
- EXT grid单元格点击时判断当前行是否可编辑
var c_gridColumns = new Ext.grid.ColumnModel({ columns: [//列模式 c_sm, { header: "内码", dataI ...
- JS---最终版本--封装缓动(变速)动画函数---增加任意多个属性&回调函数&层级&透明度
封装缓动(变速)动画函数---增加任意多个属性&回调函数&层级&透明度 相较之前的,增加了2个判断,第一个判断是不是透明度,第二个判断是不是zindex, 都不是,就只是普通属 ...