WebSocket探索

最近在項目中使用了WebSocket進行長連接通信,本文就簡要的記錄一下所用到的東西。

首先我們先學(xué)習(xí)幾個概念:
長連接
一個連接上可以連續(xù)發(fā)送多個數(shù)據(jù)包摔吏,在連接期間,如果沒有數(shù)據(jù)包發(fā)送纵装,需要雙方發(fā)鏈路檢查包征讲。
TCP/IP
TCP/IP屬于傳輸層,主要解決數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸問題橡娄,只管傳輸數(shù)據(jù)诗箍。但是那樣對傳輸?shù)臄?shù)據(jù)沒有一個規(guī)范的封裝、解析等處理挽唉,使得傳輸?shù)臄?shù)據(jù)就很難識別滤祖,所以才有了應(yīng)用層協(xié)議對數(shù)據(jù)的封裝筷狼、解析等,如HTTP協(xié)議匠童。
HTTP
HTTP是應(yīng)用層協(xié)議埂材,封裝解析傳輸?shù)臄?shù)據(jù)。從HTTP1.1開始其實就默認開啟了長連接俏让,也就是請求header中看到的Connection:Keep-alive楞遏。但是這個長連接只是說保持了(服務(wù)器可以告訴客戶端保持時間Keep-Alive:timeout=200;max=20;)這個TCP通道,直接Request - Response首昔,而不需要再創(chuàng)建一個連接通道寡喝,做到了一個性能優(yōu)化。但是HTTP通訊本身還是Request - Response勒奇。
socket
與HTTP不一樣预鬓,socket不是協(xié)議,它是在程序?qū)用嫔蠈鬏攲訁f(xié)議(可以主要理解為TCP/IP)的接口封裝赊颠。
我們知道傳輸層的協(xié)議格二,是解決數(shù)據(jù)在網(wǎng)絡(luò)中傳輸?shù)模敲磗ocket就是傳輸通道兩端的接口竣蹦。所以對于前端而言顶猜,socket也可以簡單的理解為對TCP/IP的抽象協(xié)議。
WebSocket
WebSocket是包裝成了一個應(yīng)用層協(xié)議作為socket,從而能夠讓客戶端和遠程服務(wù)端通過web建立全雙工通信痘括。websocket提供ws和wss兩種URL方案长窄。

WebSocket API


接下來我們再來看看WebSocket的API。首先我們需要做的就是創(chuàng)建一個實例:

const wsUri = 'ws://zhhy-screen.ums86.com/webSocket/memberId/pc';

let websocket  = new WebSocket(wsUri);//創(chuàng)建WebSocket

因為項目中要涉及到重連機制纲菌,所以就使用了ReconnectingWebSocket這個插件挠日,用法也十分簡單,在需要創(chuàng)建ws實例的頁面引入插件:

import ReconnectingWebSocket from './js/reconnecting-websocket.min'
// 具體的路徑根據(jù)具體項目而定

let websocket  = new ReconnectingWebSocket(wsUri);
// 然后直接將創(chuàng)建實例的語句寫成這樣就可以了翰舌。

WebSocket 事件

  • open

該事件是在服務(wù)器相應(yīng)WebSocket連接請求觸發(fā)嚣潜。

websocket.onopen = (evt) => {
    let val = 'message';
    websocket.send(JSON.stringify(val));
};
  • message

該事件是服務(wù)器有響應(yīng)信息的時候觸發(fā)。

websocket.onmessage = (evt) => {
    console.log(evt.data);
};
  //實際項目中就是在此事件中獲取返回的數(shù)據(jù)的椅贱。
  • error

該事件是出錯時觸發(fā)懂算,并且會關(guān)閉連接。

websocket.onerror = (evt) => {
    console.log('error');    
}
  • close

連接關(guān)閉時觸發(fā)庇麦,這在兩端都可以關(guān)閉犯犁。另外如果連接失敗也是會觸發(fā)的。

websocket.onclose = function(evt) {
    console.log("Connection closed.");
};  

WebSocket 方法

  • send()
    該方法用來給服務(wù)端發(fā)送消息女器。需要注意的是,必須在與服務(wù)端成功建立連接后才可以發(fā)送消息住诸,所以一般這樣處理:
if (websocket.readyState === WebSocket.OPEN) {
    websocket.send(JSON.stringify(val));
}
  • close()

該方法用來主動關(guān)閉連接驾胆。

websocket.close();

上面出現(xiàn)的readyState就是ws實例的當前狀態(tài)涣澡,一共有4種:

  • CONNECTING:值為0,表示正在連接丧诺。
  • OPEN:值為1入桂,表示連接成功,可以通信了驳阎。
  • CLOSING:值為2抗愁,表示連接正在關(guān)閉。
  • CLOSED:值為3呵晚,表示連接已經(jīng)關(guān)閉蜘腌,或者打開連接失敗。

所以可以根據(jù)websocket.readyState === WebSocket.OPEN來判斷是否連接成功饵隙。

下面我們再來看看建立ws實例的時候撮珠,瀏覽器的請求和相應(yīng):

Request URL:ws://zhhy-screen.ums86.com/webSocket/memberId/pc
Request Method:GET
Status Code:101  //狀態(tài)碼為101表示切換協(xié)議

Response Headers

Connection:upgrade
Content-Type:application/octet-stream
Date:Fri, 08 Dec 2017 02:20:11 GMT
Sec-WebSocket-Accept:M2OEhXpd4zqIkjEQtUsEr0ZSJWs= //服務(wù)器端將加密處理后的握手Key通過這個字段返回給客戶端表示服務(wù)器同意握手建立連接。
Sec-WebSocket-Extensions:permessage-deflate;client_max_window_bits=15
Server:Flaginfo_Web
ufe-result:A2
Upgrade:websocket

Request Headers

Accept-Encoding:gzip, deflate
Accept-Language:zh-CN,zh;q=0.9,en;q=0.8,fr;q=0.7
Cache-Control:no-cache
Connection:Upgrade //告知服務(wù)器當前請求連接是升級的金矛。
Cookie:_qddaz=QD.f47rqu.5a3mle.j9tqibli
Host:zhhy-screen.ums86.com
Origin:http://localhost:8083
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:jo9tTVEKTIC4UXR4HZpZMQ== //為了表示服務(wù)器同意和客戶端進行Socket連接芯急,服務(wù)器端需要使用客戶端發(fā)送的這個Key進行校驗,然后返回一個校驗過的字符串給客戶端驶俊,客戶端驗證通過后才能正式建立Socket連接娶耍。
Sec-WebSocket-Version:13 //版本,必須是13
Upgrade:websocket //告訴服務(wù)器這個HTTP連接是升級的Websocket連接饼酿。
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36 //客戶端的瀏覽器信息榕酒,可以根據(jù)此字段判斷瀏覽器版本和客戶端類型

以上就是所掌握的所有websocket知識,同時項目中還涉及到了PC的不同頁面主動向App推送消息嗜湃,其中就用到了VUEX(項目是使用VUE框架進行開發(fā))進行消息的監(jiān)聽與管理奈应,不同頁面通過commit消息this.$store.commit('sendData',data);,創(chuàng)建ws實例的頁面進行監(jiān)聽购披,監(jiān)聽到消息的變化后杖挣,就通過ws的send()方法來向app推送消息,服務(wù)器端就起到一個中間人的作用刚陡。

參考文章:WebSocket探秘

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末惩妇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子筐乳,更是在濱河造成了極大的恐慌歌殃,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝙云,死亡現(xiàn)場離奇詭異氓皱,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門波材,熙熙樓的掌柜王于貴愁眉苦臉地迎上來股淡,“玉大人,你說我怎么就攤上這事廷区∥椋” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵隙轻,是天一觀的道長埠帕。 經(jīng)常有香客問我,道長玖绿,這世上最難降的妖魔是什么敛瓷? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮镰矿,結(jié)果婚禮上琐驴,老公的妹妹穿的比我還像新娘。我一直安慰自己秤标,他們只是感情好绝淡,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著苍姜,像睡著了一般牢酵。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衙猪,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天馍乙,我揣著相機與錄音,去河邊找鬼垫释。 笑死丝格,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的棵譬。 我是一名探鬼主播显蝌,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼订咸!你這毒婦竟也來了曼尊?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤脏嚷,失蹤者是張志新(化名)和其女友劉穎骆撇,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體父叙,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡神郊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年肴裙,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涌乳。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡践宴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爷怀,到底是詐尸還是另有隱情,我是刑警寧澤带欢,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布运授,位于F島的核電站,受9級特大地震影響乔煞,放射性物質(zhì)發(fā)生泄漏吁朦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一渡贾、第九天 我趴在偏房一處隱蔽的房頂上張望逗宜。 院中可真熱鬧,春花似錦空骚、人聲如沸纺讲。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽熬甚。三九已至,卻和暖如春肋坚,著一層夾襖步出監(jiān)牢的瞬間乡括,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工智厌, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诲泌,地道東北人。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓铣鹏,卻偏偏與公主長得像敷扫,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子吝沫,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355