我有一個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