go自定义tcp消息通信

  • go自定义tcp消息通信已关闭评论
  • 132 views
  • A+
所属分类:GoLang

在业务变得越来越复杂时,我们的架构也会随之演变。在我们架构演变成TCP服务的时候,我们就需要定义客户端和服务端的消息格式。这篇文章我们将使用Go语言作为服务端语言与其它语言通信。在此之前你需要稍微了解TCP协议。

介绍

Go里面,我们使用创建一个TCP连接非常简单,只需要导入net即可。处理io也非常简单只需要导入io库即可. 就像下面的代码一样轻松实现一个tcp服务

自定义消息格式

自定义消息格式就是服务端和客户端约定好消息的格式,比如消息头是多少字节(TCP基本都是使用二进制数据),消息长度多少字节,消息内容两边按照约定的规则去读取解析数据。

比如我先将包头和包长度读取出来,解析之后一次性读出包体.

使用自定义消息格式,我们很容易判断出客户端发过来的内容是否合法,扩展性也很强,只需要这个格式实现服务就行了,也节省的带宽消耗(相对来说).

服务端实现

上面也说过实现Go的TCP服务很简单,只需要几行代码就OK,我们在上面代码的基础加上数据的读取解析和写入。 
我们需要定义一个协议结构体,拆包/解包函数.

  • 协议结构体 type protocol struct { Length uint32 //内容长度 Content []byte //内容 }
  • 解包//解包,先读取4个字节转换成整形,再读包长度字节 func UnPacket(c net.Conn) (*Protocol, error) { var ( p = &Protocol{} header = make([]byte, HEADER_LEN) ) _, err := io.ReadFull(c, header) if err != nil { return p, err } p.Length = binary.BigEndian.Uint32(header) //转换成10进制的数字 contentByte :=make([]byte, p.Length) _, e := io.ReadFull(c, contentByte) //读取内容 if e != nil { return p, e } p.Content = contentByte return p, nil }

实现了解包,我们就可以处理Content内容,可以约定为stringjson这里我们约定为json. 我们将服务协议ID定义到content里面.

  • 解析内容约定好的json格式:{ "serviceId": "", //协议名称, 比如调用, "data": { } //参数 }func (p *Protocol) parseContent() (map[string]interface{}, error) { var object map[string]interface{} unmarshal := json.Unmarshal(p.Content, &object) if unmarshal != nil { return object, unmarshal } return object, nil }

客户端实现

上面的代码已经完成了服务端解包,解析内容。我们现在实现客户端,让服务端打印客户端的内容将内容再发送给客户端. 我们需要一个组合包的方法和控制台提取输入内容的实现.

  • 生成包体 func Packet(serviceId string, content string) []byte { bytes, _ := json.Marshal(Content{ServiceId:serviceId, Data:content}) buffer := make([]byte, HEADER_LEN + len(bytes)) // 将buffer前面四个字节设置为包长度,大端序 binary.BigEndian.PutUint32(buffer[0:4], uint32(len(bytes))) copy(buffer[4:], bytes) return buffer }

完整代码

服务端
客户端

各位可以建两个文件测试下输出内容, 下面是我测试的结果:

  • 客户端Text to send: 我是骑驴找蚂蚁 Message from server: 我是骑驴找蚂蚁
  • 服务端serviceId: Hello.world, content: 我是骑驴找蚂蚁

其它语言客户端

我将使用一些其它语言实现的客户端来发送消息。在一些大型项目中多语言交互是很正常的事情。

PHP

[root@localhost]

php socketClient.php 服务端返回:我是php发的消息 #服务端 serviceId: Hello.world, content: 我是php发的消息

Java

今天的文章到此结束了, 有问题大伙可以留言,下次多加几种语言的客户端.

  • 我的微信
  • 这是我的微信扫一扫
  • weinxin
  • 我的微信公众号
  • 我的微信公众号扫一扫
  • weinxin