WebSocket规范中的代码片段:
为了使用状态码(第7.4节)/code/和可选关闭原因(第7.1.6节)/reason/开始WebSocket关闭握手,终端必须发送一个Close控制帧,具体描述见第5.5.1节,其中状态码设置为/code/,关闭原因设置为/reason/。 一旦一个终端已经发送和接收到一个Close控制帧,该终端应该按照第7.1.1节定义关闭WebSocket连接。
我正在尝试使用Gorilla WebSocket包执行关闭握手,并使用以下代码:
服务器:
// Create upgrader function
conn, err := upgrader.Upgrade(w, r, nil)
// If there is an error stop everything.
if err != nil {
fmt.Println(err)
return
}
for {
// Read Messages
_, _, err := conn.ReadMessage()
// Client is programmed to send a close frame immediately...
// When reading close frame resend close frame with same
// reason and code
conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(1000, "woops"))
fmt.Println(err)
break
}
客户端:
d := &websocket.Dialer{}
conn, _, err := d.Dial("ws://localhost:8080", nil)
if err != nil {
fmt.Println(err)
return
}
go func() {
for {
// Read Messages
_, _, err := conn.ReadMessage()
if c, k := err.(*websocket.CloseError); k {
if(c.Code == 1000) {
// Never entering since c.Code == 1005
fmt.Println(err)
break
}
}
}
}()
conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(1000, "woops"))
for {}
服务器正常读取关闭帧并输出以下内容:
但是,客户端在发送关闭消息后似乎停止了读取。websocket: close 1000 (正常): woops
ReadMessage
继续返回错误1005。我做错了什么?
select {}
而不是for {}
。前者会永远阻塞。后者会一直旋转。”OP没有从通道中读取。这就是select
的作用。conn.ReadMessage()
已经是阻塞的了。 - Artur Sapekfor {}
的。for {}
结构会浪费 CPU 时间。select {}
只会简单地阻塞程序。调用conn.ReadMessage()
不会阻塞主 goroutine。 - Charlie Tumahai