【问题标题】:Is it possible to send a web socket message when a rest api is hit? [duplicate]是否可以在点击休息 api 时发送 Web 套接字消息? [复制]
【发布时间】:2021-03-15 06:38:42
【问题描述】:

我需要扩展this tutorial 的代码以运行常规休息进程和WebSocket 服务器作为go 例程的一部分。

这是 Go 部分:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

var WS = websocket.Conn{}

func reader(conn *websocket.Conn) {
    for {
        // read in a message
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
        // print out that message for clarity
        fmt.Println(string(p))

        if err := conn.WriteMessage(messageType, p); err != nil {
            log.Println(err)
            return
        }
    }
}

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home Page")
}

func restResponsePage(w http.ResponseWriter, r *http.Request) {
    text := []byte("rest response")
    if err := WS.WriteMessage(websocket.TextMessage, text); err != nil {
        log.Println(err)
    }
    fmt.Fprintf(w, "rest response")
}

func wsEndpoint(w http.ResponseWriter, r *http.Request) {

    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

    // upgrade this connection to a WebSocket
    // connection
    WS, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
    }

    log.Println("Client Connected")
    err = WS.WriteMessage(1, []byte("Hi from server!"))
    if err != nil {
        log.Println(err)
    }

    reader(WS)
}

func setupRoutes() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/restRequest", restResponsePage)
}

func setupWsRoute() {
    http.HandleFunc("/ws", wsEndpoint)
}

func main() {
    fmt.Println("Hello World")

    go func() {
        setupWsRoute()
        log.Fatal(http.ListenAndServe(":8081", nil))
    }()

    setupRoutes()

    log.Fatal(http.ListenAndServe(":8080", nil))
}

和客户端index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Go WebSocket Tutorial</title>
  </head>
  <body>
    <h2>Hello World</h2>

    <script>
        let socket = new WebSocket("ws://127.0.0.1:8081/ws");
        console.log("Attempting Connection...");

        socket.onopen = () => {
            console.log("Successfully Connected");
            socket.send("Hi From the Client!")
        };
        
        socket.onmessage = (event) => {
            console.log("message from Server: ", event.data);
        };

        socket.onclose = event => {
            console.log("Socket Closed Connection: ", event);
            socket.send("Client Closed!")
        };

        socket.onerror = error => {
            console.log("Socket Error: ", error);
        };

    </script>
  </body>
</html>

当我点击 restRequest 端点时,在写入 restResponsePage 响应编写器 w 之前,我想向我声明为全局 var WS 并在升级连接时在读取器方法中初始化的 websocket 写入一条消息。

这在某种程度上不起作用,相反,有一个异常,我不知道如何解决它。

【问题讨论】:

  • 程序将 websocket 连接分配给用 short variable declaration 声明的局部变量。 Assign 到包级变量,而不是声明局部变量。
  • 我以为我已经在代码中这样做了...分配给包级别 var 是什么意思?
  • 包级变量就是所谓的全局变量。请注意 short variable declarationassignment 之间的语法差异::==
  • 程序现在正在使用这两个更改,谢谢 :) var WS *websocket.Conn 和 WS, _ = upgrader.Upgrade(w, r, nil)

标签: go design-patterns websocket gorilla


【解决方案1】:

感谢@ThinkGoodly 的帮助,改变了本地 WS 的声明方式并使用赋值运算符而不是短变量声明来解决问题。

这是完整的代码,以防有人想使用它。 :)

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

var WS *websocket.Conn

func reader(conn *websocket.Conn) {
    for {
        // read in a message
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
        // print out that message for clarity
        fmt.Println(string(p))

        if err := conn.WriteMessage(messageType, p); err != nil {
            log.Println(err)
            return
        }
    }
}

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home Page")
}

func restResponsePage(w http.ResponseWriter, r *http.Request) {
    text := []byte("rest response")
    if err := WS.WriteMessage(websocket.TextMessage, text); err != nil {
        log.Println(err)
    }
    fmt.Fprintf(w, "rest response")
}

func wsEndpoint(w http.ResponseWriter, r *http.Request) {

    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

    // upgrade this connection to a WebSocket
    // connection
    WS, _ = upgrader.Upgrade(w, r, nil)
    // if err != nil {
    //  log.Println(err)
    // }

    log.Println("Client Connected")
    err1 := WS.WriteMessage(1, []byte("Hi from server!"))
    if err1 != nil {
        log.Println(err1)
    }

    reader(WS)
}

func setupRoutes() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/restRequest", restResponsePage)
}

func setupWsRoute() {
    http.HandleFunc("/ws", wsEndpoint)
}

func main() {
    fmt.Println("Hello World")

    go func() {
        setupWsRoute()
        log.Fatal(http.ListenAndServe(":8081", nil))
    }()

    setupRoutes()

    log.Fatal(http.ListenAndServe(":8080", nil))
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-02
    • 2012-10-24
    • 2017-08-14
    • 2018-12-16
    • 2020-10-26
    • 1970-01-01
    • 2012-05-21
    • 2012-12-13
    相关资源
    最近更新 更多