热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自定义协议和Golang实现

自定义协议和Golang实现写在这里一是做一下总结在忘的时候方便查看,二是如果文章有错误请各位大佬喷我哈哈,欢迎指正。如果能帮到别人也挺好的。协议所谓协议就是指定一系列规则,这些规
自定义协议和Golang实现

写在这里一是做一下总结在忘的时候方便查看,二是如果文章有错误请各位大佬喷我哈哈,欢迎指正。如果能帮到别人也挺好的。

协议

所谓协议就是指定一系列规则,这些规则使想要交流的双方或多方可以正常通信交流。如我们说的汉语就是协议,如果不按照汉语规则说话,交流的人就听不懂对方说什么,汉语和英语就是不同的协议,用汉语和只会英语的人交流,人家也听不懂你说啥。在计算机中,入参出参是协议,最简单的服务端rest接口是协议,系统实现一层层的网络协议使计算机可以互相通信。

自定义协议

自定义协议就是在现有协议满足不了我们需求时,在现有协议之上构建的满足我们自己程序的通信需求的协议。目前的操作系统,会把我们应用需要的底层网络协议实现好,这对我们来说是透明的,但是在我们写rest时,是不是需要定义接口呢,这接口就是我们自定义的一种协议,通过定义请求参数,响应参数,让客户端和我们写好的服务端程序进行交互,这就是自定义的协议。

定义自定义协议

在TCP基础上自定义协议,主要就是通信双方规定一个头,头后面是传递的数据。头中规定一些参数,比如传递的消息前10个字节是头,头最前面2个字节是个固定魔数,让你知道我是根据这个协议来通信的,如果不支持这个协议的话,就可以直接关掉这个连接了。跟着魔数的4个字节是整个包中数据的长度,这个长度不包括头,需要长度的原因是TCP协议面向的是流,会把应用原本一个一个发送的包一股脑的扔给对方,如果不用长度字段,我们就很有可能拿到了多个包的数据。最后4个字节是个校验码,校验收到的包的数据是否有错误,主要是防止通信时被篡改。
此时我们就完成了我们自定义协议的定义。只需要发送端在将数据写入TCP前,在数据前面加入这个头,接收端接收到数据时,按照这个头的定义拿取数据,就可以完成双方的通信了。

GO中定义协议

自定义了一个Conn结构体,结构体中包含连接,元数据,scan是用来从真正的socket中获取数据,通过socket连接new一个scan,然后通过scan的split方法注册一个分割数据的函数,这里包装在了RegisterSplitFunc()函数中,scan会通过我们注册函数中的分割方式来分割数据,通过Scan()方法分割一次数据,获取返回数据使用scan.Bytes()

type Conn struct {
c net.Conn
meta metadata.Metadata
scan *bufio.Scanner
}
func (c *Conn) Read() (b []byte, err error) {
if c.c == nil {
return nil, errors.New("conn is nil")
}
if c.scan == nil {
//包装过的函数,做了一个scan.Split(splitFunc)的操作
c.RegisterSplitFunc()
}
if c.scan.Scan() {
b = c.scan.Bytes()
} else {
c.c.Close()
err = errors.New("conn scan error")
}
return
}
//write方法中的头由模数0x0102, 长度len(data)+4组成
//头后面跟着数据
func (c *Conn) Write(data []byte) (err error) {
if len(data) > math.MaxUint16 {
return errors.New("data too big")
}
buf := bytes.Buffer{}
binary.Write(&buf, binary.BigEndian, []byte{0x01,0x02})
binary.Write(&buf, binary.BigEndian, uint16(len(data)+4))
binary.Write(&buf, binary.BigEndian, data)
_, err = c.c.Write(buf.Bytes())
return
}

分割函数

func MySplitFunc(data []byte, atEOF bool) (advance int, token []byte, err error) {
//判断长度,魔数
if len(data) <4 || data[0] != 0x01 || data[1] != 0x02 {
err = errors.New("protocol error")
return
}
var l uint16
//获取header
err = binary.Read(bytes.NewReader(data[2:4]), binary.BigEndian, &l)
if err != nil {
logs.Error("binary.Read error(%v)", err)
return
}
//通过长度读取数据,advance为读取的长度,包括头和数据,data是读取的数据
if int(l) <= len(data) {
advance, token, err = int(l), data[:int(l)], nil
}
if atEOF {
err = errors.New("EOF")
}
return
}

总结

以上为在golang中自定义简单通信协议的方式。


推荐阅读
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了在go语言中利用(*interface{})(nil)传递参数类型的原理及应用。通过分析Martini框架中的injector类型的声明,解释了values映射表的作用以及parent Injector的含义。同时,讨论了该技术在实际开发中的应用场景。 ... [详细]
  • Ihavethisfollowinginputfile:我有以下输入文件:test.csvdone_cfg,,,,port<0>,clk_in,subcktA,ins ... [详细]
  • 开发笔记:Spark Java API 之 CountVectorizer
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了SparkJavaAPI之CountVectorizer相关的知识,希望对你有一定的参考价值。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文讨论了使用差分约束系统求解House Man跳跃问题的思路与方法。给定一组不同高度,要求从最低点跳跃到最高点,每次跳跃的距离不超过D,并且不能改变给定的顺序。通过建立差分约束系统,将问题转化为图的建立和查询距离的问题。文章详细介绍了建立约束条件的方法,并使用SPFA算法判环并输出结果。同时还讨论了建边方向和跳跃顺序的关系。 ... [详细]
  • 颜色迁移(reinhard VS welsh)
    不要谈什么天分,运气,你需要的是一个截稿日,以及一个不交稿就能打爆你狗头的人,然后你就会被自己的才华吓到。------ ... [详细]
  • 在本教程中,我们将看到如何使用FLASK制作第一个用于机器学习模型的RESTAPI。我们将从创建机器学习模型开始。然后,我们将看到使用Flask创建AP ... [详细]
  • Thisissuewasoriginallyopenedbyashashicorp/terraform#5664.Itwasmigratedhe ... [详细]
  • (七)k8s集群调度
    一、调度说明1.1、简介Scheduler ... [详细]
  • 我上个月有幸参加了在西雅图召开的PASS(ProfessionalAssociationforSQLServer)峰会。我的同事MattMasson做了 ... [详细]
  • 按照之前我对map的理解,map中的数据应该是有序二叉树的存储顺序,正常的遍历也应该是有序的遍历和输出,但实际试了一下,却发现并非如此,网上查了下,发现从Go1开始,遍历的起始节点就是随机了,当然随机 ... [详细]
  • golang字符串转Time类型问题小记
      最近在做项目中,遇到了golang字符串转Time类型的问题。调研后发现golang提供了俩种方式,即time.Parse跟time.ParseInLocation。俩种方式差 ... [详细]
author-avatar
蔡心怡湖人永蓉
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有