<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      初探和實現websocket心跳重連(npm: websocket-heartbeat-js)

      提示:文章最下方有倉庫地址

       

      心跳重連緣由

       

      websocket是前后端交互的長連接,前后端也都可能因為一些情況導致連接失效并且相互之間沒有反饋提醒。因此為了保證連接的可持續性和穩定性,websocket心跳重連就應運而生。

      在使用原生websocket的時候,如果設備網絡斷開,不會立刻觸發websocket的任何事件,前端也就無法得知當前連接是否已經斷開。這個時候如果調用websocket.send方法,瀏覽器才會發現鏈接斷開了,便會立刻或者一定短時間后(不同瀏覽器或者瀏覽器版本可能表現不同)觸發onclose函數。

      后端websocket服務也可能出現異常,造成連接斷開,這時前端也并沒有收到斷開通知,因此需要前端定時發送心跳消息ping,后端收到ping類型的消息,立馬返回pong消息,告知前端連接正常。如果一定時間沒收到pong消息,就說明連接不正常,前端便會執行重連。

      為了解決以上兩個問題,以前端作為主動方,定時發送ping消息,用于檢測網絡和前后端連接問題。一旦發現異常,前端持續執行重連邏輯,直到重連成功。

       

       

      如何實現

      在websocket實例化的時候,我們會綁定一些事件:

      var ws = new WebSocket(url);
      ws.onclose = function () {
          //something
      };
      ws.onerror = function () {
          //something
      };
              
      ws.onopen = function () {
         //something
      };
      ws.onmessage = function (event) {
         //something
      }

      如果希望websocket連接一直保持,我們會在close或者error上綁定重新連接方法。

      ws.onclose = function () {
          reconnect();
      };
      ws.onerror = function () {
          reconnect();
      };
          

      這樣一般正常情況下失去連接時,觸發onclose方法,我們就能執行重連了。

       

      那么針對斷網情況的心跳重連,怎么實現呢,我們只需要定時的發送消息,去觸發websocket.send方法,如果網絡斷開了,瀏覽器便會觸發onclose。

      簡單的實現:

      var heartCheck = {
          timeout: 60000,//60ms
          timeoutObj: null,
          reset: function(){
              clearTimeout(this.timeoutObj);
           this.start();
      }, start: function(){ this.timeoutObj = setTimeout(function(){ ws.send("HeartBeat"); }, this.timeout) } } ws.onopen = function () { heartCheck.start(); };
      ws.onmessage = function (event) {
          heartCheck.reset();
      }

      如上代碼,heartCheck 的 reset和start方法主要用來控制心跳的定時。

      什么條件下執行心跳:

      當onopen也就是連接成功后,我們便開始start計時,如果在定時時間范圍內,onmessage獲取到了后端的消息,我們就重置倒計時,

      距離上次從后端獲取到消息超過60秒之后,執行心跳檢測,看是不是斷連了,這個檢測時間可以自己根據自身情況設定。

       

      判斷前端websocket斷開(斷網但不限于斷網的情況):

      當心跳檢測執行send方法之后,如果當前websocket是斷開狀態(或者說斷網了),發送超時之后,瀏覽器的websocket會自動觸發onclose方法,重連就會立刻執行(onclose方法體綁定了重連事件),如果當前一直是斷網狀態,重連會2秒(時間是自己代碼設置的)執行一次直到網絡正常后連接成功。

      如此一來,判斷前端斷開websocket的心跳檢測就實現了。為什么說是前端主動斷開,因為當前這種情況主要是通過前端websocket.send來檢測并觸發的onclose,后面說后端斷開的情況。

       

      我本想測試websocket超時時間,又發現了一些新的問題

      1. 在chrome中,如果心跳檢測 也就是websocket實例執行send之后,15秒內沒發送到另一接收端,onclose便會執行。那么超時時間是15秒。

      2. 我又打開了Firefox ,Firefox在斷網7秒之后,直接執行onclose。說明在Firefox中不需要心跳檢測便能自動onclose。

      3.  同一代碼, reconnect方法 在chrome 執行了一次,Firefox執行了兩次。當然我們在幾處地方(代碼邏輯處和websocket事件處)綁定了reconnect(),

      所以保險起見,我們還是給reconnect()方法加上一個鎖,保證只執行一次

       

      目前來看不同的瀏覽器,有不同的機制,無論瀏覽器websocket自身會不會在斷網情況下執行onclose,加上心跳重連后,已經能保證onclose的正常觸發。  其實這是由于socket本身就有底層的心跳,socket消息發送不出去的時候,會等待一定時間看是否能在這個時間之內再次連接上,如果超時便會觸發onclose。

       

      判斷后端斷開:

          如果后端因為一些情況斷開了ws,是可控情況下的話,會下發一個斷連的通知,這樣會觸發前端weboscket的onclose方法,我們便會重連。

      如果因為一些異常斷開了連接,前端是不會感應到的,所以如果前端發送了心跳一定時間之后,后端既沒有返回心跳響應消息,前端也沒有收到任何其他消息的話,我們就能斷定后端發生異常斷開了。

      一點特別重要的發送心跳到后端,后端收到消息之后必須返回消息,否則超過60秒之后會判定后端主動斷開了。再改造下代碼:

       

      var heartCheck = {
          timeout: 60000,//60ms
          timeoutObj: null,
          serverTimeoutObj: null,
          reset: function(){
              clearTimeout(this.timeoutObj);
              clearTimeout(this.serverTimeoutObj);
           this.start();
          },
          start: function(){
              var self = this;
              this.timeoutObj = setTimeout(function(){
                  ws.send("HeartBeat");
                  self.serverTimeoutObj = setTimeout(function(){
                      ws.close();//如果onclose會執行reconnect,我們執行ws.close()就行了.如果直接執行reconnect 會觸發onclose導致重連兩次
                  }, self.timeout)
              }, this.timeout)
          },
      }
      
      ws.onopen = function () {
         heartCheck.start();
      };
      ws.onmessage = function (event) {
          heartCheck.reset();
      }
      ws.onclose = function () {
          reconnect();
      };
      ws.onerror = function () {
          reconnect();
      };
       

       

      PS:

          因為目前我們這種方式會一直重連如果沒連接上或者斷連的話,如果有兩個設備同時登陸并且會踢另一端下線,一定要發送一個踢下線的消息類型,這邊接收到這種類型的消息,邏輯判斷后就不再執行reconnect,否則會出現一只相互擠下線的死循環。

       

      結語

      由于斷開等原因可能會導致發送的數據沒有發送出去,要保證數據不丟失的話,可以做消息回執,也就是a給b發送消息id=1,b返回收到id=1的消息,如果沒有回執a可以再次發送消息id=1。

      由上文可以看到,我們使用了前端發送ping,后端返回pong的這樣一種心跳的方式。也有一種方式是后端主動發送心跳,前端判斷是否超時。因為ws鏈接必須是前端主動請求建立連接,因此重連肯定是給前端來做,所以判斷重連邏輯都是寫在前端。

      上面所說第二種方式是讓服務端發送心跳,前端來接收,這樣的方式會多節約一點帶寬,因為如果是前端發送心跳,后端需要返回心跳,也就是ping pong的過程會有兩次數據傳遞。  而后端來發送心跳的話,就只需要發送ping,前端不需要回應。但是這樣造成了一個問題。前端需要和后端約定好心跳間隔,比如后端設置10秒發送一次心跳,那前端就需要設置一個安全值,比如距離上次收到心跳超過12秒還沒收到下一個心跳就重連。這種方式的問題在于調節時間就變得不那么靈活了,需要雙方都同時確定一個時間約定。后端的邏輯也會比較多一點。
      而如果前端來發送ping 后端返回pong的話,那么間隔時間就只需要前端自己控制了。加上我的代碼把收到的任何后端信息都可以當作是連接正常,從而重置心跳時間,這樣也節約了一些請求次數。
      使用我這樣的方式,后端比較輕松,只需要在 onmessage 寫一段代碼,大概如下:

      if(msg=='heartbeat') socket.send(anything);

       

      封裝了一個npm包,歡迎使用

      https://github.com/zimv/websocket-heartbeat-js

      https://www.npmjs.com/package/websocket-heartbeat-js

      posted @ 2016-08-25 20:31  子慕大詩人  閱讀(141310)  評論(63)    收藏  舉報
      主站蜘蛛池模板: 人人妻人人做人人爽夜欢视频 | 国产精品色哟哟成人av| 国产精品天干天干综合网| 欧美日本在线| 麻豆国产va免费精品高清在线| 人妻教师痴汉电车波多野结衣| 国内精品一区二区不卡| 国产无遮挡裸体免费久久| 欧洲一区二区中文字幕| 三上悠亚在线精品二区| 日韩一区二区三区av在线| 久操热在线视频免费观看| 国产婷婷综合在线视频中文| 日韩精品 在线 国产 丝袜| 久久羞羞色院精品全部免费| 中文字幕乱码一区二区免费| 国产成人精品无码免费看夜聊软件 | 欧美极品少妇×xxxbbb| 一区二区中文字幕久久| 国产美女深夜福利在线一| 亚洲精品国产中文字幕| 熟女人妻视频| 久久成人国产精品免费软件| 免费人成网站视频在线观看| 商河县| 成熟妇女性成熟满足视频| 老司机午夜精品视频资源| 亚洲精品有码在线观看| 欧美人与动牲猛交A欧美精品 | 中文字幕在线观看一区二区| 亚洲欧美综合精品成| 在线精品国产中文字幕| 国精品无码一区二区三区在线蜜臀 | 少妇粗大进出白浆嘿嘿视频| 孕妇怀孕高潮潮喷视频孕妇| 久久精品色一情一乱一伦| 国产熟女一区二区五月婷| 99视频精品全部免费 在线| 亚洲人成网站77777在线观看| 国外av片免费看一区二区三区| AV毛片无码中文字幕不卡|