@
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 |
- 接收前端信息
| 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) { |
| |
| 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:= "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) |
| |
| 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!"); |
| 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> |
- 结果


【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律