欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

golang Gin framework with websocket

程序员文章站 2022-03-25 17:01:32
"概述" "golang websocket 库" "示例" "后端" "前端" "结论" 概述 对于 golang 的 web 开发, 之前写过 2 篇 blog, 分别介绍了: 1. 在 Gin 框架下, 各类 http API 的开发方法(包括文件上传, 下载等) "golang Web 方案 ......

概述

对于 golang 的 web 开发, 之前写过 2 篇 blog, 分别介绍了:

  1. 在 gin 框架下, 各类 http api 的开发方法(包括文件上传, 下载等) golang web 方案
  2. gin 框架下反向代理的使用:

这里再给之前的 web 方案中加上 websocket 的部分, 基本就能涵盖日常开发所需的所有接口类型了.

golang websocket 库

这里使用的 websocket 库来自 gorilla web toolkit

下面用代码来演示如何在 gin 框架中结合 websocket api

示例

后端

后端提供 2 种 api, 分别支持 text 格式和 json 格式的消息 示例中的 api 每次收到消息后, 返回 10 次

  1  package main
  2  
  3  import (
  4   "log"
  5   "net/http"
  6   "strconv"
  7   "time"
  8  
  9   "github.com/gin-contrib/static"
 10   "github.com/gin-gonic/gin"
 11   "github.com/gorilla/websocket"
 12  )
 13  
 14  var upgrader = websocket.upgrader{
 15   checkorigin: func(r *http.request) bool {
 16     return true
 17   },
 18  }
 19  
 20  // websocket返回text 格式
 21  func textapi(c *gin.context) {
 22   //升级get请求为websocket协议
 23   ws, err := upgrader.upgrade(c.writer, c.request, nil)
 24   if err != nil {
 25     log.println("error get connection")
 26     log.fatal(err)
 27   }
 28   defer ws.close()
 29   //读取ws中的数据
 30   mt, message, err := ws.readmessage()
 31   if err != nil {
 32     log.println("error read message")
 33     log.fatal(err)
 34   }
 35  
 36   //写入ws数据, pong 10 times
 37   var count = 0
 38   for {
 39     count++
 40     if count > 10 {
 41       break
 42     }
 43  
 44     message = []byte(string(message) + " " + strconv.itoa(count))
 45     err = ws.writemessage(mt, message)
 46     if err != nil {
 47       log.println("error write message: " + err.error())
 48     }
 49     time.sleep(1 * time.second)
 50   }
 51  }
 52  
 53  //websocket返回 json格式
 54  func jsonapi(c *gin.context) {
 55   //升级get请求为websocket协议
 56   ws, err := upgrader.upgrade(c.writer, c.request, nil)
 57   if err != nil {
 58     log.println("error get connection")
 59     log.fatal(err)
 60   }
 61   defer ws.close()
 62   var data struct {
 63     a string `json:"a"`
 64     b int    `json:"b"`
 65   }
 66   //读取ws中的数据
 67   err = ws.readjson(&data)
 68   if err != nil {
 69     log.println("error read json")
 70     log.fatal(err)
 71   }
 72  
 73   //写入ws数据, pong 10 times
 74   var count = 0
 75   for {
 76     count++
 77     if count > 10 {
 78       break
 79     }
 80  
 81     err = ws.writejson(struct {
 82       a string `json:"a"`
 83       b int    `json:"b"`
 84       c int    `json:"c"`
 85     }{
 86       a: data.a,
 87       b: data.b,
 88       c: count,
 89     })
 90     if err != nil {
 91       log.println("error write json: " + err.error())
 92     }
 93     time.sleep(1 * time.second)
 94   }
 95  }
 96  
 97  func websocketgin() {
 98   r := gin.default()
 99   r.get("/json", jsonapi)
100   r.get("/text", textapi)
101  
102   // static files
103   r.use(static.serve("/", static.localfile("./public", true)))
104  
105   r.noroute(func(c *gin.context) {
106     c.file("./public/index.html")
107   })
108  
109   r.run(":8000")
110  }

后端代码中有个静态文件的路由 r.use(static.serve("/", static.localfile("./public", true)))
只要将下面的前端代码命名为 index.html 并放在和后端代码根目录下的 public 文件夹中,
就可以在启动后端之后, 直接通过访问 *" 来显示页面了

前端

前端很简单, 就是在页面初始化完成后创建 websocket 连接, 然后发送消息并显示接受到的消息

 1  <!doctype html>
 2  <html lang="en">
 3    <head>
 4      <meta charset="utf-8" />
 5      <title>index</title>
 6    </head>
 7    <body>
 8      <h1>test websocket</h1>
 9      <p id="message-json"></p>
10      <p id="message-text"></p>
11      <script>
12        function jsonws() {
13          var ws = new websocket("ws://localhost:8000/json");
14          //连接打开时触发
15          ws.onopen = function (evt) {
16            console.log("connection open ...");
17            var obj = { a: "bb", b: 2 };
18            ws.send(json.stringify(obj));
19          };
20          //接收到消息时触发
21          ws.onmessage = function (evt) {
22            console.log("received message: " + evt.data);
23            document.getelementbyid("message-json").innertext += evt.data;
24          };
25          //连接关闭时触发
26          ws.onclose = function (evt) {
27            console.log("connection closed.");
28          };
29        }
30  
31        function textws() {
32          var ws = new websocket("ws://localhost:8000/text");
33          //连接打开时触发
34          ws.onopen = function (evt) {
35            console.log("connection open ...");
36            ws.send("text message");
37          };
38          //接收到消息时触发
39          ws.onmessage = function (evt) {
40            console.log("received message: " + evt.data);
41            document.getelementbyid("message-text").innertext = evt.data;
42          };
43          //连接关闭时触发
44          ws.onclose = function (evt) {
45            console.log("connection closed.");
46          };
47        }
48        // 启动 websocket
49        jsonws();
50        textws();
51      </script>
52    </body>
53  </html>

结论

运行之后, 就可以看到页面上显示的 message 了, 发送一次信息, 会收到 10 条返回.