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