我有一个Websocket
服务器写在go
与包github.com/gorilla/websocket
。websocket客户端onmessage刷新浏览器后破坏
服务器有2个用于接收和发送消息的环路。在HTTP处理程序的实现如下所示:
upgrader, errChan := websocket.Upgrader{}, make(chan error)
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// incoming messages
go func() {
for {
message := Message{}
if err := ws.ReadJSON(&message); err != nil {
errChan <- err
}
handleMessage(message)
}
}()
// outgoing messages
go func() {
for {
message := <-global.outgoingMessage
if err = ws.WriteMessage(websocket.TextMessage, message); err != nil {
errChan <- err
}
}
}()
err = <- errChan
ws.Close()
客户端应用程序使用反应,该应用程序使用的消息作为状态。当应用程序启动时,websocket连接建立,并且onopen回调触发对初始数据的请求。响应被用于应用程序状态的onmessage捕获。实现如下所示:
var ws = new WebSocket("ws://localhost:8080/app")
ws.onerror = function(err) {
alert(err)
}
ws.onmessage = function(m) {
var state = JSON.parse(m.data)
global.app.setState(state)
}
ws.onopen = function() {
ws.send('{"type":"init"}')
}
有了这个设置,我已经注意到是我第一次火起来的应用程序和浏览页面的一切工作正常。一旦我刷新浏览器,它不再有效。我可以拨打ws.send('{"type":"init"}')
并查看服务器发送的响应,但onmessage
回调不会被触发。经过多次尝试呼叫ws.send('{"type":"init"}')
后,onmessage
最终会被调用一次,并且应用状态被加载。如果我杀了并重新启动应用程序,则会发生相同的行为。
想法?
该应用程序泄漏goroutines。看到[这个问题](http://stackoverflow.com/questions/38090545/are-goroutines-garbage-collected-together-with-their-channels)的解释。多个输出程序从'global.outgoingMessage'接收吗?如果是这样,确保足够的消息发送到'global.outgoingMessage'以满足所有正在运行的输出例程? –
@MellowMarmot你是对的。 'global.outgoingMessage'只能从这个处理程序中接收,但它是一个全局通道,所以当刷新浏览器websocket连接时,上一个连接仍在通道上监听。如果你发布答案,我会接受它。谢谢! – believesInSanta