04-websocket链接

@

1. 升级接口

1.1 语法

- 升级接口

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

- 关闭

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

- 接收前端信息

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

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("停止发送")
	}
}

2. 获取信息从websocket传出

2.1 语法

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

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
}

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")
}

4. 前端调用测试

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

<!DOCTYPE html>
<html>
 
<head>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
    <title>TestWebsocket</title>
 
    <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>
  • 结果
    在这里插入图片描述

posted on 2022-11-10 09:06  运维开发玄德公  阅读(23)  评论(0编辑  收藏  举报  来源

导航