話說 html5 之後,Web 端要及時通訊多了 SSE(Server-Sent-Event) 和 WebSocket。
SSE簡單來說就是長輪詢(Long-polling)的進階版,透過javaScript API處理,只能由Server單向發送給Client。
Websocket 提供全雙工、雙向的資料傳輸,這點相當適合用在線上聊天室或遊戲。
不過即時性要求不高時,又想在瀏覽器間兼容,長輪詢(Long-polling)這種方式,還是一種選擇。
網路上的比較文章很多,這裡不贅述,想談談一個實作 Websocket 的眉角。
心跳包(HeartBeat)的重要性
在第一次握手(Handshake)後,便會建立一個長連線。而網路斷線等意外,並不會呼叫 Server端的 OnClose(),導致 Server 端一廂情願推送、苦苦等候。
透過定時/不定時確認連線狀態,除了能清除占用的連線資源,也能及時處理聊天室使用者斷線,比如 Client 端的斷線重連,增進服務體驗。
RFC 6455中定義了幾種 WebSocket 資料傳輸單位(frame):text data、binary data、ping/pong、close等。
其中,兩端都可以透過 ping/pong 來做心跳檢測。
A Ping frame may serve either as a keepalive or as a means to verify that the remote endpoint is still responsive.
當Client收到一個 Ping,必須回傳 Pong,告訴 Server: 他還活著。反之亦然。
Upon receipt of a Ping frame, an endpoint MUST send a Pong frame in response, unless it already received a Close frame. It SHOULD respond with a Pong frame as soon as is practical.
注意:
WebSocket 是基於 TCP 協議,
但 TCP 的 keep-alive 機制(同樣是確認狀態),
無法確認當前應用層的 Application 連線可不可用。
WebSockets ping/pong, why not TCP keepalive? - Stack Overflow
在實踐上,假設兩端有頻繁的數據互動,那透過定時的心跳檢測,便會浪費傳輸流量。通常會記錄上一次接收/發送 Websocket 訊息的時間,假設超過預設時間,才發送心跳包。
簡單的做法如下:
寫的很好,其實你可以留在鐵人賽再發文的說? 說不定可以拿到獎項
謝謝你的鼓勵!目前就是單純紀錄跟分享,希望自己在實做跟概念上都有所進步~