猿问

获取 WebSocket 错误关闭发送当我导航到其他页面

我收到错误websocket:当我尝试将数据从服务器端发送到客户端(仪表板页面)时,关闭发送。当我导航到主页并返回到仪表板页面时发生错误。最初使用仪表板页面

时一切正常 我的仪表板页面代码


  let socket = new ReconnectingWebSocket("ws://127.0.0.1:8004/wsendpoint");

        console.log("Attempting Connection...");


        socket.onopen = () => {

            console.log("Successfully Connected");

          

        };

        socket.onclose = event => {

            console.log("Socket Closed Connection: ", event);

         

        };

        socket.onerror = error => {

            console.log("Socket Error: ", error);

         

        };

        socket.onmessage = function (event) {

            console.log("message received: " + event.data);

        }

我的服务器端代码(编写器和读取器)


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("upgrade error %s", err)

    }


    defer ws.Close()


    go writer(ws) 

    go reader(ws)

}

写入器,当新数据从数据库传入时从通道获取数据


func writer(conn *websocket.Conn) {


    for {

        singleset := <-singleorder // get data from channel

        jsonString, err := json.Marshal(singleset ) 

        err = conn.WriteMessage(1, []byte(jsonString))

        if err != nil {

            log.Println(err)

        }

    }

读取器,从客户端读取数据


func reader(conn *websocket.Conn) {

    for {

        _, p, err := conn.ReadMessage() //what is message type?

        if err != nil {

            log.Println("there is errors%s", err)

            return

        }

    }

}

我还收到错误 WebSocket 在建立连接之前被关闭,而重新连接-websocket.min.js:1 WebSocket 连接到“ws://127.0.0.1:8004/wsendpoint”失败:WebSocket 在建立连接之前被关闭。


正如你所看到的,所有的代码都非常简单,因为我刚刚开始学习websocket并遵循简单的教程。我试图在网上搜索,但网络工作者对我来说似乎有点复杂,并看到了乒乓球方法,但我不确定如果我导航它是否仍然有效。我可以在主页上建立websocket,以便连接不会关闭吗?因为我在客户端只有两个页面。


提前感谢您有关如何处理这些情况的任何指导!


MYYA
浏览 129回答 1
1回答

潇湘沐

处理离开页面、页面关闭或错误的导航的基本策略是:客户端在页面加载时创建 websocket 连接。服务器期望客户端连接来来去去,并在客户端连接错误时清理资源。这就是为什么您收到错误“websocket:关闭发送”的原因:当用户离开页面时,浏览器会向服务器发送一条关闭消息,作为websocket关闭握手的一部分。Gorilla 包通过向客户端发送另一条关闭消息来响应关闭消息。从那时起,服务器无法在连接上发送消息。发送关闭消息后,连接从写入方法返回错误。关闭消息作为 websocket 读取方法中的错误返回。若要解决此问题,请修改代码以处理常规错误。无需专门处理闭合握手。下面是更新的代码。该函数为读取器创建一个通道,以向编写器发出读取器已完成的信号。该语句被删除,因为读取者和写入者将负责关闭连接。wsEndpointdefer ws.Close()func wsEndpoint(w http.ResponseWriter, r *http.Request) {&nbsp; &nbsp; upgrader.CheckOrigin = func(r *http.Request) bool { return true }&nbsp; &nbsp; // upgrade this connection to a WebSocket connection&nbsp; &nbsp; ws, err := upgrader.Upgrade(w, r, nil)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; log.Println("upgrade error %s", err)&nbsp; &nbsp; }&nbsp; &nbsp; done := make(chan struct{})&nbsp; &nbsp; &nbsp;&nbsp; &nbsp; go writer(ws, done)&nbsp;&nbsp; &nbsp; go reader(ws, done)}读取器在返回时关闭连接。它还关闭通道以向写入器发出读取器已完成的信号。donefunc reader(conn *websocket.Conn, done chan struct{}) {&nbsp; &nbsp; defer conn.Close()&nbsp; &nbsp; defer close(done)&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; _, p, err := conn.ReadMessage() //what is message type?&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println("there is errors%s", err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}编写器还会在返回时关闭连接。当连接关闭时,对连接的读取会立即返回一个错误,导致读取 goroutine 完成。编写器在频道上等待。当通道被读取器关闭时,通道上的接收将产生零值。编写器在写入错误时返回,而不是像问题中那样永远循环。donefunc writer(conn *websocket.Conn, done chan struct{}) {&nbsp; &nbsp; defer conn.Close()&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; select {&nbsp; &nbsp; &nbsp; &nbsp; case <-done:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // the reader is done, so return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; case singleset := <-singleorder: // get data from channel&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; jsonString, err := json.Marshal(singleset )&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; err = conn.WriteMessage(1, []byte(jsonString))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log.Println(err)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}应用程序应期望由于多种原因(包括用户离开页面)而关闭连接。发送到通道的代码可能需要知道连接已关闭,但我们在这里看不到该代码。我会留给你来弄清楚如何处理这个问题。singleorder
随时随地看视频慕课网APP

相关分类

Go
我要回答