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

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

原文地址:https://www.cnblogs.com/taoshihan/p/12057619.html

时间: 2024-08-03 14:23:51

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

[Go] 轻量服务器框架基础TCP服务模块

框架要先把整体的结构定义好,一般都是在$GOPATH目录的src下建立自己的目录 zinterface是一些接口的定义 znet就是接口的具体实现 IServer.go package zinterface type IServer interface{ Start() Stop() Server() } server.go一个tcp服务端的基本业务,简单的原样回显 package znet import ( "fmt" "log" "net"

[Go] 轻量服务器框架全局配置的实现以及解析json

在一个应用中经常需要有一个配置文件,可以对代码中的参数进行配置,可以使用一个json文件来对应一个struct的对象,进行全局配置 建一个conf/zinx.json作为配置文件 { "Name":"zinxServer", "Host":"0.0.0.0", "TcpPort":8888 } 建一个utils/GlobalObj.go  utils包,比如下面这个 func init()函数可以在导包的同

阿里云轻量服务器价格及轻量与ECS服务器区别比较

https://yq.aliyun.com/articles/221647 摘要: 阿里云轻量应用服务器价格表及介绍,关于轻量应用服务器和ECS服务器的性能对比 阿里云轻量应用服务器是阿里云新推出的服务器,本文介绍阿里云轻量服务器的价格,已经何为"轻量"?轻量与阿里云ECS服务器有什么区别?轻量性能就一定不如ECS服务器吗? 什么是轻量应用服务器?轻量应用服务器是面向单机应用场景的新一代计算服务,提供精品应用一键部署,支持一站式的域名.网站.安全.运维.应用管理等服务,极大地优化了搭建

阿里云轻量服务器LAMP镜像部署网站踩过的坑第一期

阿里云的轻量服务器真的很多坑,刚完成3个网站部署在一台轻量服务器的工作,虚拟主机配置文件,php源码解析,mysql.httpd和php不是系统变量等等各种问题:准备一个一个来填坑,在这感谢51CTO讲师段老师的帮助,3年前在他那学的红帽7.0:碰到什么写什么,可能有点水,但是都是实操经验,现在网上大多都是copy,自己也没验证过,还有一些是初学者虚拟机玩配置,对实际操作帮助不大: 今天先说一下轻量服务器的虚拟主机配置文件 碰到新的系统,先查看系统版本,下面是阿里云轻量服务器的版本信息 [[em

阿里云轻量服务器部署PHP网站简述(基于Lamp)

一:首先登陆阿里云账户购买轻量服务器(这里就不详细介绍啦) 二:进去以后是这样的 然后其他的一些设置参考https://blog.csdn.net/cuiji4724/article/details/81395364(内容如下) 一.介绍环境1.首先进入操控台找到轻量应用服务器(若找不到可以在下方)产品与服务里面搜. 2.进入轻量应用服务器,找到重置系统,应用镜像选择LAMP,系统镜像选择CentOS,点击确认更换 (这里我也进行了应用镜像的更换,但是更换了多次没有成功,还是显示的是WrodPr

C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性

C/C++ socket编程教程之九:TCP的粘包问题以及数据的无边界性 上节我们讲到了socket缓冲区和数据的传递过程,可以看到数据的接收和发送是无关的,read()/recv() 函数不管数据发送了多少次,都会尽可能多的接收数据.也就是说,read()/recv() 和 write()/send() 的执行次数可能不同. 例如,write()/send() 重复执行三次,每次都发送字符串"abc",那么目标机器上的 read()/recv() 可能分三次接收,每次都接收"

TCP通信粘包问题分析和解决

TCP通信粘包问题分析和解决(全) 在socket网络程序中,TCP和UDP分别是面向连接和非面向连接的.因此TCP的socket编程,收发两端(客户端和服务器端)都要有成对的socket,因此,发送端为了将多个发往接收端的包,更有效的发到对方,使用了优化方法(Nagle算法),将多次间隔较小.数据量小的数据,合并成一个大的数据块,然后进行封包.这样,接收端,就难于分辨出来了,必须提供科学的拆包机制. 对于UDP,不会使用块的合并优化算法,这样,实际上目前认为,是由于UDP支持的是一对多的模式,

Android轻量缓存框架--ASimpleCache

[转] 大神真面目 稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! 编辑推荐: 做Android应用开发的同学们相信对“缓存”这个词不陌生,缓存可能有多方面的概念,这里大概列举下程序开发的缓存大概有哪些: 1.服务端控制缓存 如volley请求库,便是通过服务端的“Cache-Control”和“max-age”来告诉客户端有没有缓存以及缓存的时间,也是推荐的使用

关于TCP的粘包和拆包

问题产生 一个完整的业务可能会被TCP拆分成多个包进行发送,也有可能把多个小的包封装成一个大的数据包发送,这个就是TCP的拆包和封包问题. 下面可以看一张图,是客户端向服务端发送包: 1. 第一种情况,Data1和Data2都分开发送到了Server端,没有产生粘包和拆包的情况. 2. 第二种情况,Data1和Data2数据粘在了一起,打成了一个大的包发送到Server端,这个情况就是粘包. 3. 第三种情况,Data2被分离成Data2_1和Data2_2,并且Data2_1在Data1之前到