(摘) golang库:gotalk 专注于进程间的通信,致力于简化通信协议和流程

声明:内容源自网络,版权归原作者所有。若有侵权请在网页聊天中联系我

原文地址:https://zhuanlan.zhihu.com/p/374016707

提供简洁、清晰的 API;
支持 TCP,WebSocket 等协议;
采用非常简单而又高效的传输协议格式,便于抓包调试;
内置了 JavaScript 文件gotalk.js,方便开发基于 Web 网页的客户端程序;

go get -u github.com/rsms/gotalk

一个简单示例:

// get-started/server/server.go
package main

import (
  "log"

  "github.com/rsms/gotalk"
)

func main() {
  gotalk.Handle("echo", func(in string) (string, error) {
    return in, nil
  })
  if err := gotalk.Serve("tcp", ":8080", nil); err != nil {
    log.Fatal(err)
  }
}

客户端

func main() {
  s, err := gotalk.Connect("tcp", ":8080")
  if err != nil {
    log.Fatal(err)
  }

  for i := 0; i < 5; i++ {
    var echo string
    if err := s.Request("echo", "hello", &echo); err != nil {
      log.Fatal(err)
    }

    fmt.Println(echo)
  }

  s.Close()
}

WebSocket

func main() {
  gotalk.Handle("echo", func(in string) (string, error) {
    return in, nil
  })

  http.Handle("/gotalk/", gotalk.WebSocketHandler())
  http.Handle("/", http.FileServer(http.Dir(".")))
  if err := http.ListenAndServe(":8080", nil); err != nil {
    log.Fatal(err)
  }
}

gotalk为了方便 Web 程序的编写,将 WebSocket 通信细节封装在一个 JavaScript 文件gotalk.js中。可以直接从仓库中的 js 目录下获取使用。接着我们编写页面index.html,引入gotalk.js:

<!DOCTYPE HTML>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <script type="text/javascript" src="gotalk/gotalk.js"></script>
  </head>
  <body>
    <input id="txt">
    <button id="snd">send</button><br>
    <script>
    let c = gotalk.connection()
      .on('open', () => log(`connection opened`))
      .on('close', reason => log(`connection closed (reason: ${reason})`))
    let btn = document.querySelector("#snd")
    let txt = document.querySelector("#txt")
    btn.onclick = async () => {
      let content = txt.value
      if (content.length === 0) {
        alert("no message")
        return
      }
      let res = await c.requestp('echo', content)
      log(`reply: ${JSON.stringify(res, null, 2)}`)
      return false
    }
    function log(message) {
      document.body.appendChild(document.createTextNode(message))
      document.body.appendChild(document.createElement("br"))
    }
    </script>
  </body>
</html>

协议格式

gotalk采用基于 ASCII 的协议格式,设计为方便人类阅读且灵活的。每条传输的消息都分为几个部分:类型标识、请求ID、操作、消息内容。

类型标识:只用一个字节,用来表示消息的类型,是请求消息还是响应消息,流式消息还是非流式的,错误、心跳和通知也都有其特定的类型标识。请求 ID:用 4 个字节表示,方便匹配响应。由于gotalk可以同时发送任意个请求并接收之前请求的响应。所以需要有一个 ID 来标识接收到的响应对应之前发送的哪条请求。操作:即为我们上面定义的消息名,例如"echo"。消息内容:使用长度 + 实际内容格式。

看一个官方请求的示例:

+—————— SingleRequest | +—————- requestID “0001” | | +——— operation “echo” (text3Size 4, text3Value “echo”) | | | +- payloadSize 25 | | | | r0001004echo00000019{“message”:“Hello World”}

r:表示这是一个单条请求。0001:请求 ID 为 1,这里采用十六进制编码。004echo:这部分表示操作为"echo",在实际字符串内容前需要指定长度,否则接收方不知道内容在哪里结束。004指示"echo"长度为 4,同样采用十六进制编码。00000019{"message":"Hello World"}:这部分是消息的内容。同样需要指定长度,十六进制00000019表示长度为 25。

详细格式可以查看官方文档。