1 回答

TA貢獻1788條經驗 獲得超4個贊
該websocket: close sent錯誤表明服務器向客戶端發送了關閉消息。因為應用程序服務器代碼不發送消息,所以連接必須發送消息以響應來自客戶端的關閉消息。
關閉消息作為錯誤從 websocket 讀取方法返回。因為沒有記錄任何消息,所以客戶端一定發送了“離開”關閉消息(唯一沒有記錄的錯誤)。
當websocket連接返回錯誤時,讀寫goroutine關閉連接返回。連接未保持打開狀態。
讀取和寫入 goroutine 不會檢測到另一個已關閉連接,直到從連接上的方法調用返回錯誤。讀取 goroutine 會快速檢測到關閉的連接,因為它始終在讀取,但寫入 goroutine 可能會有延遲。這可能是應用程序的問題
要讓寫入 goroutine 快速退出,請使用通道向寫入 goroutine 發出信號。有可能dataChan可用于此目的,但我不確定,因為該問題不包含有關如何管理頻道的信息。假設通道可以使用,讀取 goroutine 應該關閉dataChan。writer 應該檢測到關閉的通道并退出 goroutine:
...
for {
? ? select {
? ? case data, ok := <-datachan:
? ? ? ? if !ok {
? ? ? ? ? ?// Done writing, return
? ? ? ? ? ?return
? ? ? ? }
? ? ? ? ws.SetWriteDeadline(time.Now().Add(writeWait))
? ? ? ? err := ws.WriteJSON(&data)
? ? ? ? if err != nil {
? ? ? ? ? ? conf.Log.Debugf("Failed to write data to Websocket: %v", err)
? ? ? ? ? ? return
? ? ? ? }
? ? ? ? ...
這是Gorilla Chat Example使用的方法。
如果dataChan不能使用,為此引入一個新的通道。在處理程序中創建通道并將通道傳遞給讀寫 goroutines:
?done := make(chan struct{})
?go allUserWebsocketWriter(ws, stop, datachan)
?go PingResponse(ws, stop)
從讀取 goroutine 返回時關閉通道:
func PingResponse(ws *websocket.Conn, done chan struct{}) {
? ? defer close(done)
? ? conf := storage.GetConfig()
? ? ...
在寫gorountine的通道上選擇:
...
for {
? ? select {
? ? case <-done:
? ? ? ? return
? ? case data := <-datachan:
? ? ? ? ws.SetWriteDeadline(time.Now().Add(writeWait))
? ? ? ? err := ws.WriteJSON(&data)
? ? ? ? ...
這導致寫 goroutine 在讀 goroutine 退出后快速退出。
這兩種方法都降低了在連接上寫入返回錯誤的可能性websocket: close sent,但它們并沒有消除這種可能性。該錯誤是預期的,因為讀取 goroutine 可以在寫入 goroutine 寫入消息之前關閉連接。
無論如何,證據是客戶端正在關閉連接。未關閉的連接不是問題所在。
- 1 回答
- 0 關注
- 346 瀏覽
添加回答
舉報