關(guān)于socket的一些探究

聽說小米今天破發(fā)了子姜。作為一個偽米粉慌植,我還是比較談定的驯嘱,如果你的身邊有一個人時長提醒你--蘋果干到小米現(xiàn)在的位置需要50年,小米只需要10幾年為什么;小米負(fù)債千億人民幣...等等謠言陕靠。說了這么多迂尝,小米依舊是小米脱茉,我依舊是哪個普普通通的屌絲程序員。

事件起因:

我在剛開始接觸到項目的時候雹舀,看到一位同事為了保證本地狀態(tài)和遠(yuǎn)端的狀態(tài)芦劣,是用http進(jìn)行輪詢的粗俱,就像下面的代碼一樣:

{
      //代碼都是臨時手寫的 可能有不完善的見諒啊
    let xmlhttp;
    let isFishish = false;
    let time = setInterval(()=>{
        if(isFishish){
            clearInterval(time)
        }else{
            getHttpRequest();
        }
    },3000)


    function getHttpRequest(){
        xmlhttp=null;
        if(window.XMLHttpRequest)
        {
            xmlhttp=new XMLHttpRequest();
        }else if (window.ActiveXObject)
        {
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }
        if (xmlhttp!=null)
        {
            xmlhttp.onreadystatechange=state_Change;
            xmlhttp.open("GET",url,true);
            xmlhttp.send(null);
        }
        else
        {
            alert("Your browser does not support XMLHTTP.");
        }
    }

    function state_Change(){
        if (xmlhttp.readyState==4)
        {
            if (xmlhttp.status==200)
            {// 200 = OK
                // ...our code here...
            } else {
                alert("Problem retrieving XML data");
            }
        }
    }
}

這種輪詢的方式有好有壞说榆,能夠初步的達(dá)到用戶的需求,但是用戶的數(shù)據(jù)改變卻又不能即使的反饋給用戶寸认。算了就這樣說好像沒什么可塑性签财,就直接用一個生活小實例來描述吧。

  • http請求
    client:辦公室有沒有吃的偏塞?
    server:沒有
    client:辦公室還沒有吃的唱蒸?
    server:沒有
    client:現(xiàn)在有吃的沒?
    server:沒有
  • socket請求:
    client: 我們來建立socket連接吧灸叼,如果你有累點重點的活兒就告訴我
    server:求之不得神汹,連接好了
    client:有活兒就立馬告訴我
    server:好的
    server:幫我把這數(shù)據(jù)用Excel表格列出來
    client:好的,弄好了
    server:謝謝

從上面的例子上面就可以看出socket其實是可以古今,由服務(wù)端發(fā)起主動想客戶端發(fā)送數(shù)據(jù)的屁魏。

介紹一下socket:

前面說了這么多大體都提及了socket,但是具體的socket是什么捉腥?有什么優(yōu)點氓拼?基本都介紹的模棱兩可。現(xiàn)在來系統(tǒng)的介紹一下

  • 介紹一下socket
    WebSocket是為解決客戶端與服務(wù)端實時通信而產(chǎn)生的技術(shù)抵碟。其本質(zhì)是先通過HTTP/HTTPS協(xié)議進(jìn)行握手后創(chuàng)建一個用于交換數(shù)據(jù)的TCP連接桃漾,
  • socket的優(yōu)點在哪兒:
    以前我們實現(xiàn)推送技術(shù),用的都是輪詢拟逮,在特點的時間間隔有瀏覽器自動發(fā)出請求撬统,將服務(wù)器的消息主動的拉回來,在這種情況下敦迄,我們需要不斷的向服務(wù)器 發(fā)送請求宪摧,然而HTTP request 的header是非常長的,里面包含的數(shù)據(jù)可能只是一個很小的值颅崩,這樣會占用很多的帶寬和服務(wù)器資源几于。會占用大量的帶寬和服務(wù)器資源。
    WebSocket API最偉大之處在于服務(wù)器和客戶端可以在給定的時間范圍內(nèi)的任意時刻沿后,相互推送信息沿彭。在建立連接之后,服務(wù)器可以主動傳送數(shù)據(jù)給客戶端尖滚。
    此外喉刘,服務(wù)器與客戶端之間交換的標(biāo)頭信息很小瞧柔。
    WebSocket并不限于以Ajax(或XHR)方式通信,因為Ajax技術(shù)需要客戶端發(fā)起請求睦裳,而WebSocket服務(wù)器和客戶端可以彼此相互推送信息造锅;
    此后服務(wù)端與客戶端通過此TCP連接進(jìn)行實時通信。

我是這樣使用socket的

關(guān)于socket的使用廉邑,我是直接用最基礎(chǔ)的源碼來寫的哥蔚,雖然最后知道了js里面有一個常用的庫,但是想想呢蛛蒙?既然是寫文章就直接用最基礎(chǔ)的東西更能說明問題糙箍。

{
    initWebSocket(){ //初始化weosocket
                //ws地址
        const wsuri = process.env.WS_API + "/websocket/threadsocket";
        this.websock = new WebSocket(wsuri);
        this.websock.onmessage = this.websocketonmessage 
        this.websock.onerror = this.websocketerror
        this.websock.onopen = this.websocketonopen
        this.websock.onclose = this.websocketclose
    },
    websocketonmessage(e){ //數(shù)據(jù)接收
        const redata = JSON.parse(e.data);
        console.log(redata.value);
    },
    websocketsend(data){//數(shù)據(jù)發(fā)送
        this.websock.send(data);
    },
    websocketclose(e){  //關(guān)閉
        console.log("connection closed (" + e.code + ")");
    }
}

當(dāng)然,我在這里使用的是vue牵祟,這套代碼深夯,自己的項目也在使用,是可以使用的诺苹。我在這里呢咕晋?主要來談一下websocket的四個方法:

  • readyState: 返回實例對象的當(dāng)前狀態(tài),一共有下面四種:
CONNECTING:值為0,表示正在連接收奔。
OPEN:值為1掌呜,表示連接成功,可以通信了筹淫。
CLOSING:值為2站辉,表示連接正在關(guān)閉。
CLOSED:值為3损姜,表示連接已經(jīng)關(guān)閉饰剥,或者打開連接失敗。
  • onopen:用于指定連接成功后的回調(diào)函數(shù)
    當(dāng)然我也看到很多人這么來寫:
websock.addEventListener('open', function (event) {
  // dosomethings...
});
  • onerror: 用于指定報錯時的回調(diào)函數(shù)
  • onmessage: 用于指定收到服務(wù)器數(shù)據(jù)后的回調(diào)函數(shù)
  • onclose: 用于指定連接關(guān)閉后的回調(diào)函數(shù)
  • send: 發(fā)送socket消息

最后再聊一塊錢的

當(dāng)然摧阅,我在開發(fā)的時候遇到很常見的一個小問題汰蓉,那就是socket容易斷開。我最后這一塊錢就想由斷線重連談起棒卷。
我在這里首先來介紹一下前面提到的一個回調(diào)onclose,這個如果存在連接中斷的情況會調(diào)用該回調(diào)顾孽,告知客戶端。首先看一下參數(shù):

onclose參數(shù)

closeEvent

由上面的圖解知道比规,close會有三個參數(shù):code若厚、reasonwasClean

  • code:返回一個 unsigned short 類型的數(shù)字, 表示服務(wù)端發(fā)送的關(guān)閉碼, 以下為已分配的狀態(tài)碼.
狀態(tài)碼 名稱 描述
0–999 保留段, 未使用.
1000 CLOSE_NORMAL 正常關(guān)閉; 無論為何目的而創(chuàng)建, 該鏈接都已成功完成任務(wù).
1001 CLOSE_GOING_AWAY 終端離開, 可能因為服務(wù)端錯誤, 也可能因為瀏覽器正從打開連接的頁面跳轉(zhuǎn)離開.
1002 CLOSE_PROTOCOL_ERROR 由于協(xié)議錯誤而中斷連接.
1003 CLOSE_UNSUPPORTED 由于接收到不允許的數(shù)據(jù)類型而斷開連接 (如僅接收文本數(shù)據(jù)的終端接收到了二進(jìn)制數(shù)據(jù)).
1004 <wbr> 保留. <wbr>其意義可能會在未來定義.
1005 CLOSE_NO_STATUS 保留. <wbr> 表示沒有收到預(yù)期的狀態(tài)碼.
1006 CLOSE_ABNORMAL 保留. <wbr>用于期望收到狀態(tài)碼時連接非正常關(guān)閉 (也就是說, 沒有發(fā)送關(guān)閉幀).
1007 Unsupported Data 由于收到了格式不符的數(shù)據(jù)而斷開連接 (如文本消息中包含了非 UTF-8 數(shù)據(jù)).
1008 Policy Violation 由于收到不符合約定的數(shù)據(jù)而斷開連接. 這是一個通用狀態(tài)碼, 用于不適合使用 1003 和 1009 狀態(tài)碼的場景.
1009 CLOSE_TOO_LARGE 由于收到過大的數(shù)據(jù)幀而斷開連接.
1010 Missing Extension 客戶端期望服務(wù)器商定一個或多個拓展, 但服務(wù)器沒有處理, 因此客戶端斷開連接.
1011 Internal Error 客戶端由于遇到?jīng)]有預(yù)料的情況阻止其完成請求, 因此服務(wù)端斷開連接.
1012 Service Restart 服務(wù)器由于重啟而斷開連接. [Ref]
1013 Try Again Later 服務(wù)器由于臨時原因斷開連接, 如服務(wù)器過載因此斷開一部分客戶端連接. [Ref]
1014 <wbr> 由 WebSocket 標(biāo)準(zhǔn)保留以便未來使用.
1015 TLS Handshake 保留. <wbr>表示連接由于無法完成 TLS 握手而關(guān)閉 (例如無法驗證服務(wù)器證書).
10161999 <wbr> 由 WebSocket 標(biāo)準(zhǔn)保留以便未來使用.
20002999 <wbr> 由 WebSocket 拓展保留使用.
30003999 <wbr> 可以由庫或框架使用. <wbr>不應(yīng)由應(yīng)用使用. 可以在 IANA 注冊, 先到先得.
40004999 <wbr> 可以由應(yīng)用使用.
  • reson:返回一個 DOMString用以表示服務(wù)器關(guān)閉連接的原因. 這是由服務(wù)器和子協(xié)議決定的.
  • wasClean: 返回一個 Boolean用以表示連接是否完全關(guān)閉.

由上面的基礎(chǔ)我們就可以在onclose回調(diào)里面做重連代碼蜒什,我是這樣寫的

{
    onclose(e){
        if(!Object,is(e.code,1000)){
            if(!e.wasClean) {
                this.websock.close()
            }
            setTimeout(()=>{
                initWebSocket();
            },4000)
        }
    }
}

我這樣寫呢测秸?暫時也沒有發(fā)現(xiàn)什么錯誤,但是也不一定是全正確的。如果諸位看官在使用的時候有任何瑕疵請立即告訴我霎冯,我如果在使用中有任何不舒服的铃拇,我也會及時更新的。謝謝呢沈撞,您咧?独蟆!

說在最后

最近老是9點半左右下班缠俺,大清早旁邊的工地又不停的在吵显晶,攪的人無神無主、五雷轟頂...哇啊啊啊晋修,算了 或許這就是生命吧吧碾。反正一切的一切都是在炫耀自己懶罷了凰盔。最近呢墓卦?也準(zhǔn)備和大學(xué)室友寫一個項目,其中包含前端户敬、后端落剪、Android端。如果有看官希望一起開發(fā)尿庐、或者有興趣的話忠怖,請聯(lián)系我。大家一起邊開發(fā)邊學(xué)習(xí)邊成長抄瑟。好了凡泣,午時已到,準(zhǔn)備睡覺皮假,嗯 洗澡去了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鞋拟,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子惹资,更是在濱河造成了極大的恐慌贺纲,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,807評論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褪测,死亡現(xiàn)場離奇詭異猴誊,居然都是意外死亡,警方通過查閱死者的電腦和手機侮措,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評論 3 399
  • 文/潘曉璐 我一進(jìn)店門懈叹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人分扎,你說我怎么就攤上這事澄成。” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評論 0 363
  • 文/不壞的土叔 我叫張陵环揽,是天一觀的道長略荡。 經(jīng)常有香客問我,道長歉胶,這世上最難降的妖魔是什么汛兜? 我笑而不...
    開封第一講書人閱讀 60,188評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮通今,結(jié)果婚禮上粥谬,老公的妹妹穿的比我還像新娘。我一直安慰自己辫塌,他們只是感情好漏策,可當(dāng)我...
    茶點故事閱讀 69,185評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著臼氨,像睡著了一般掺喻。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上储矩,一...
    開封第一講書人閱讀 52,785評論 1 314
  • 那天感耙,我揣著相機與錄音,去河邊找鬼持隧。 笑死即硼,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的屡拨。 我是一名探鬼主播只酥,決...
    沈念sama閱讀 41,220評論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼呀狼!你這毒婦竟也來了裂允?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,167評論 0 277
  • 序言:老撾萬榮一對情侶失蹤赠潦,失蹤者是張志新(化名)和其女友劉穎叫胖,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體她奥,經(jīng)...
    沈念sama閱讀 46,698評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡瓮增,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,767評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了哩俭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绷跑。...
    茶點故事閱讀 40,912評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖凡资,靈堂內(nèi)的尸體忽然破棺而出砸捏,到底是詐尸還是另有隱情谬运,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評論 5 351
  • 正文 年R本政府宣布垦藏,位于F島的核電站梆暖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏掂骏。R本人自食惡果不足惜轰驳,卻給世界環(huán)境...
    茶點故事閱讀 42,254評論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望弟灼。 院中可真熱鬧级解,春花似錦、人聲如沸田绑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽掩驱。三九已至芒划,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間昙篙,已是汗流浹背腊状。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評論 1 274
  • 我被黑心中介騙來泰國打工诱咏, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留苔可,地道東北人。 一個月前我還...
    沈念sama閱讀 49,359評論 3 379
  • 正文 我出身青樓袋狞,卻偏偏與公主長得像焚辅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苟鸯,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,922評論 2 361

推薦閱讀更多精彩內(nèi)容