• golang Gin framework with websocket


    概述

    对于 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 文件夹中,
    就可以在启动后端之后, 直接通过访问 *http://localhost:8000" 来显示页面了

    前端

    前端很简单, 就是在页面初始化完成后创建 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 条返回.

  • 相关阅读:
    ant
    Java中的值传递和引用传递
    待解决的问题
    Ant生成文件解析
    JUnit初学
    遍历枚举
    2013年5月阅读链接
    《C Primer Plus》阅读笔记(3)
    《C Primer Plus》阅读笔记(2)
    《C Primer Plus》阅读笔记(4)
  • 原文地址:https://www.cnblogs.com/wang_yb/p/12711377.html
Copyright © 2020-2023  润新知