• GO语言gin框架实战-04-websocket链接


    1. 升级接口

    1.1 语法

    - 升级接口

    • 语法
    func (u *Upgrader) Upgrade(w http.ResponseWriter, r *http.Request, responseHeader http.Header) (*Conn, error)
    
    • 1
    • 语法示例
    ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    
    • 1

    - 关闭

    • 语法
    func (c *Conn) Close() error
    
    • 1
    • 语法示例
    defer ws.Close()
    
    • 1

    - 接收前端信息

    • 语法
    func (c *Conn) ReadMessage() (messageType int, p []byte, err error)
    
    • 1
    • 语法示例
    _, message, err := ws.ReadMessage()
    
    • 1

    1.2 完整示例

    package router
    
    import (
    	"crow-logger/service"
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"github.com/gorilla/websocket"
    	"log"
    	"net/http"
    )
    
    func GetLog(c *gin.Context) {
        //升级接口
    	ws, err := upgrader.Upgrade(c.Writer, c.Request, nil)
    
    	if err != nil {
    		fmt.Print("升级websocket连接错误:", err)
    		return
    	}
    	defer ws.Close()
    
        //传参(这个不是本例重点,结构体也就不放出来了)
    	var sshInfo service.SshInfo
    	sshInfo.UserName = c.DefaultQuery("user_name","root")
    	sshInfo.SshPort = c.DefaultQuery("ssh_port","22")
    	sshInfo.IpAddr = c.Query("ip_addr")
    	sshInfo.ProjectName = c.Query("project_name")
    	sshInfo.ServiceName = c.Query("service_name")
    	// 接受消息
    	_, message, err := ws.ReadMessage()
    	if err != nil {
    		fmt.Println("接收错误:", err)
    	} else {
    		fmt.Println("接收到前端消息:", string(message))
    		err := service.SendCmd(ws,sshInfo)
    		if err !=nil {
    			c.JSON(400,gin.H{"status":"END"} )
    			return
    		}
    
    		log.Println("停止发送")
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43

    2. 获取信息从websocket传出

    2.1 语法

    func (c *Conn) WriteMessage(messageType int, data []byte) error
    
    • 1
    • 语法示例
    err = conn.WriteMessage(websocket.TextMessage,[]byte(txt))
    
    • 1

    2.2 完整示例

    接前边的示例,ssh到服务器,将docker-compose的实时日志传入 websocket

    package service
    import (
    	"context"
    	"crow-logger/config"
    	"github.com/gorilla/websocket"
    	"github.com/yahoo/vssh"
    	"log"
    	"time"
    )
    
    func SendCmd(conn *websocket.Conn,sshInfo SshInfo)(err error)  {
        //前边这些都是ssh获取信息【不是本例重点】
    	vs := vssh.New().Start()
    	log.Println(sshInfo)
    	config,err := vssh.GetConfigPEM(sshInfo.UserName,config.IdRSAFilePath)
    	if err !=nil {
    		return err
    	}
    	for _, addr := range []string{sshInfo.IpAddr+":"+sshInfo.SshPort} {
    		err := vs.AddClient(addr, config, vssh.SetMaxSessions(10))
    		if err != nil {
    			log.Println(err)
    		}
    	}
    	vs.Wait()
    
    	ctx, cancel := context.WithCancel(context.Background())
    	defer cancel()
    
    	//cmd:= "ping  10.10.xxx.101"
    	cmd:= "cd /data/"+sshInfo.ProjectName+"/"+sshInfo.ServiceName +" && docker-compose logs -f"
    	log.Println(cmd)
    
    
    	timeout, _ := time.ParseDuration("10m")
    	respChan := vs.Run(ctx,cmd,timeout)
    
    	resp := <- respChan
    	if err = resp.Err(); err != nil {
    		log.Fatal(err)
    	}
    
    	stream := resp.GetStream()
    	defer stream.Close()
    
    	for stream.ScanStdout() {
    		txt := stream.TextStdout()
    		log.Println(txt)
    		//将ssh得到的信息通过websocket接口循环传出
    		err := conn.WriteMessage(websocket.TextMessage,[]byte(txt))
    		if err != nil{
    			log.Println("写入错误",err)
    			return err
    		}
    	}
    	return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    3. 配置router

    gin的router设置没有特别之处,和之前一样。

    package router
    
    
    import (
    	"github.com/gin-gonic/gin"
    )
    
    func ServerWebsocket()  {
    	r := gin.Default()
        ……
    	deployment := r.Group("/api/v1/logger")
    	{
    		deployment.GET("/",GetLog)
    		……
    	}
    	r.Run(":1911")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    4. 前端调用测试

    一个简约的前端测试代码,和后端建立websocket链接。根据需要修改地址和传参:

    DOCTYPE html>
    <html>
     
    <head>
        <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
        <title>TestWebsockettitle>
     
        <script type="text/javascript">
            function LinkServer() {
                // 声明连接
                var Server_Com;
                if ("WebSocket" in window) {
                    Server_Com = new WebSocket("ws://127.0.0.1:1911/api/v1/logger/?user_name=root&ssh_port=22&ip_addr=10.10.239.97&project_name=crust&service_name=gis-server");
                    console.log("新建连接到->127.0.0.1:1911");
                }
     
                // 建立连接后发送
                Server_Com.onopen = function() {
     
                    Server_Com.send("Hello Server!"); // Web Socket 已连接上,使用 send() 方法发送数据
                    console.log("已连接上服务器");
                }
     
                // 接收服务器消息
                Server_Com.onmessage = function(event) {
                    var recv_msg = event.data;
     
                    if (recv_msg == "Hello Client!") {
                        console.log("接收到服务器的问候: " + recv_msg); // 用于提示收到信息
                    } else {
                        document.getElementById("Time").textContent = recv_msg; // 实时更新显示服务器发回的时间
                        console.log("接收到服务器数据: " + recv_msg);
                    }
                }
            }
        script>
    head>
     
    <body>
        <p>接收到的信息:p>
        <p id="Time">crow-logger测试p>
     
        <button onclick="LinkServer()">连接button>
     
    body>
     
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 结果
      在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    抽象工厂
    CRM系统销售漏斗有哪几个阶段?
    Java EnumMap remove()方法具有什么功能呢?
    Spring Gateway 网关常见配置说明
    钉钉企业微应用开发C#+VUE
    MySQL导入导出视图
    5.5V-65V Vin同步降压控制器,具有线路前馈SCT82630DHKR
    瑞萨e2studio(29)----SPI速率解析
    L33.linux命令每日一练 -- 第五章 Linux信息显示与搜索文件命令 -- du和date
    Win10电脑重装系统更新关闭了还自动打开怎么解决?
  • 原文地址:https://blog.csdn.net/xingzuo_1840/article/details/127744279