看完讓你徹底搞懂Websocket原理

偶然在知乎上看到一篇回帖,瞬間覺得之前看的那么多資料都不及這一篇回帖讓我對websocket的認(rèn)識深刻有木有自沧。所以轉(zhuǎn)到我博客里,分享一下树瞭。比較喜歡看這種博客拇厢,讀起來很輕松,不枯燥晒喷,沒有布道師的陣仗孝偎,純粹為分享。廢話這么多了凉敲,最后再贊一個(gè)~

一衣盾、websocket與http

WebSocket是HTML5出的東西(協(xié)議),也就是說HTTP協(xié)議沒有變化爷抓,或者說沒關(guān)系势决,但HTTP是不支持持久連接的(長連接,循環(huán)連接的不算)

首先HTTP有1.1和1.0之說蓝撇,也就是所謂的keep-alive果复,把多個(gè)HTTP請求合并為一個(gè),但是Websocket其實(shí)是一個(gè)新協(xié)議渤昌,跟HTTP協(xié)議基本沒有關(guān)系虽抄,只是為了兼容現(xiàn)有瀏覽器的握手規(guī)范而已,也就是說它是HTTP協(xié)議上的一種補(bǔ)充可以通過這樣一張圖理解

有交集独柑,但是并不是全部迈窟。

另外Html5是指的一系列新的API,或者說新規(guī)范忌栅,新技術(shù)车酣。Http協(xié)議本身只有1.0和1.1,而且跟Html本身沒有直接關(guān)系。骇径。通俗來說躯肌,你可以用HTTP協(xié)議傳輸非Html數(shù)據(jù),就是這樣=破衔。=

再簡單來說清女,層級不一樣。

二晰筛、Websocket是什么樣的協(xié)議嫡丙,具體有什么優(yōu)點(diǎn)

首先,Websocket是一個(gè)持久化的協(xié)議读第,相對于HTTP這種非持久的協(xié)議來說曙博。簡單的舉個(gè)例子吧,用目前應(yīng)用比較廣泛的PHP生命周期來解釋怜瞒。

HTTP的生命周期通過Request來界定父泳,也就是一個(gè)Request一個(gè)Response,那么在HTTP1.0中吴汪,這次HTTP請求就結(jié)束了惠窄。

在HTTP1.1中進(jìn)行了改進(jìn),使得有一個(gè)keep-alive漾橙,也就是說杆融,在一個(gè)HTTP連接中,可以發(fā)送多個(gè)Request霜运,接收多個(gè)Response脾歇。但是請記住Request = Response, 在HTTP中永遠(yuǎn)是這樣淘捡,也就是說一個(gè)request只能有一個(gè)response藕各。而且這個(gè)response也是被動(dòng)的,不能主動(dòng)發(fā)起案淋。

教練座韵,你BB了這么多,跟Websocket有什么關(guān)系呢踢京?_(:з」∠)_好吧,我正準(zhǔn)備說Websocket呢宦棺。瓣距。

首先Websocket是基于HTTP協(xié)議的,或者說借用了HTTP的協(xié)議來完成一部分握手代咸。

首先我們來看個(gè)典型的Websocket握手(借用Wikipedia的蹈丸。。)

GET /chat HTTP/1.1

Host: server.example.com

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

Origin: http://example.com

熟悉HTTP的童鞋可能發(fā)現(xiàn)了,這段類似HTTP協(xié)議的握手請求中儡遮,多了幾個(gè)東西柬脸。我會順便講解下作用鸦采。

Upgrade: websocket

Connection: Upgrade

這個(gè)就是Websocket的核心了,告訴Apache闻伶、Nginx等服務(wù)器:注意啦,我發(fā)起的是Websocket協(xié)議够话,快點(diǎn)幫我找到對應(yīng)的助理處理~不是那個(gè)老土的HTTP蓝翰。

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

首先,Sec-WebSocket-Key是一個(gè)Base64 encode的值女嘲,這個(gè)是瀏覽器隨機(jī)生成的畜份,告訴服務(wù)器:泥煤,不要忽悠窩欣尼,我要驗(yàn)證尼是不是真的是Websocket助理爆雹。

然后,Sec_WebSocket-Protocol是一個(gè)用戶定義的字符串愕鼓,用來區(qū)分同URL下钙态,不同的服務(wù)所需要的協(xié)議。簡單理解:今晚我要服務(wù)A拒啰,別搞錯(cuò)啦~

最后驯绎,Sec-WebSocket-Version是告訴服務(wù)器所使用的Websocket Draft(協(xié)議版本),在最初的時(shí)候谋旦,Websocket協(xié)議還在Draft階段剩失,各種奇奇怪怪的協(xié)議都有,而且還有很多期奇奇怪怪不同的東西册着,什么Firefox和Chrome用的不是一個(gè)版本之類的拴孤,當(dāng)初Websocket協(xié)議太多可是一個(gè)大難題。甲捏。不過現(xiàn)在還好演熟,已經(jīng)定下來啦~大家都使用的一個(gè)東西~ 脫水:服務(wù)員,我要的是13歲的噢→_→

然后服務(wù)器會返回下列東西司顿,表示已經(jīng)接受到請求芒粹, 成功建立Websocket啦!

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Sec-WebSocket-Protocol: chat

這里開始就是HTTP最后負(fù)責(zé)的區(qū)域了大溜,告訴客戶化漆,我已經(jīng)成功切換協(xié)議啦~

Upgrade: websocket

Connection: Upgrade

依然是固定的,告訴客戶端即將升級的是Websocket協(xié)議钦奋,而不是mozillasocket座云,lurnarsocket或者shitsocket疙赠。

然后,Sec-WebSocket-Accept這個(gè)則是經(jīng)過服務(wù)器確認(rèn)朦拖,并且加密過后的Sec-WebSocket-Key圃阳。?服務(wù)器:好啦好啦,知道啦璧帝,給你看我的ID CARD來證明行了吧捍岳。。

后面的裸弦,Sec-WebSocket-Protocol則是表示最終使用的協(xié)議祟同。

至此,HTTP已經(jīng)完成它所有工作了理疙,接下來就是完全按照Websocket協(xié)議進(jìn)行了晕城。具體的協(xié)議就不在這闡述了。

——————技術(shù)解析部分完畢——————

你TMD又BBB了這么久窖贤,那到底Websocket有什么鬼用砖顷,http long poll,或者ajax輪詢不都可以實(shí)現(xiàn)實(shí)時(shí)信息傳遞么赃梧。

好好好滤蝠,年輕人,那我們來講一講Websocket有什么用授嘀。來給你吃點(diǎn)胡(蘇)蘿(丹)卜(紅)

三物咳、Websocket的作用

在講Websocket之前,我就順帶著講下long poll和ajax輪詢的原理蹄皱。

ajax輪詢

ajax輪詢的原理非常簡單览闰,讓瀏覽器隔個(gè)幾秒就發(fā)送一次請求,詢問服務(wù)器是否有新信息巷折。

場景再現(xiàn):

客戶端:啦啦啦压鉴,有沒有新信息(Request)

服務(wù)端:沒有(Response)

客戶端:啦啦啦,有沒有新信息(Request)

服務(wù)端:沒有锻拘。油吭。(Response)

客戶端:啦啦啦,有沒有新信息(Request)

服務(wù)端:你好煩啊署拟,沒有啊婉宰。。(Response)

客戶端:啦啦啦推穷,有沒有新消息(Request)

服務(wù)端:好啦好啦芍阎,有啦給你。(Response)

客戶端:啦啦啦缨恒,有沒有新消息(Request)

服務(wù)端:谴咸。。骗露。岭佳。。沒萧锉。珊随。。柿隙。沒叶洞。。禀崖。沒有(Response) —- loop

long poll

long poll其實(shí)原理跟ajax輪詢差不多衩辟,都是采用輪詢的方式,不過采取的是阻塞模型(一直打電話波附,沒收到就不掛電話)艺晴,也就是說,客戶端發(fā)起連接后掸屡,如果沒消息封寞,就一直不返回Response給客戶端。直到有消息才返回仅财,返回完之后狈究,客戶端再次建立連接,周而復(fù)始盏求。

場景再現(xiàn):

客戶端:啦啦啦抖锥,有沒有新信息,沒有的話就等有了才返回給我吧(Request)

服務(wù)端:額风喇。宁改。 等待到有消息的時(shí)候。魂莫。來 給你(Response)

客戶端:啦啦啦还蹲,有沒有新信息,沒有的話就等有了才返回給我吧(Request) -loop

從上面可以看出其實(shí)這兩種方式耙考,都是在不斷地建立HTTP連接谜喊,然后等待服務(wù)端處理,可以體現(xiàn)HTTP協(xié)議的另外一個(gè)特點(diǎn)倦始,被動(dòng)性斗遏。

何為被動(dòng)性呢,其實(shí)就是鞋邑,服務(wù)端不能主動(dòng)聯(lián)系客戶端诵次,只能有客戶端發(fā)起账蓉。

簡單地說就是,服務(wù)器是一個(gè)很懶的冰箱(這是個(gè)梗)(不會逾一、不能主動(dòng)發(fā)起連接)铸本,但是上司有命令,如果有客戶來遵堵,不管多么累都要好好接待箱玷。

說完這個(gè),我們再來說一說上面的缺陷(原諒我廢話這么多吧OAQ)

從上面很容易看出來陌宿,不管怎么樣锡足,上面這兩種都是非常消耗資源的。

ajax輪詢 需要服務(wù)器有很快的處理速度和資源壳坪。(速度)long poll 需要有很高的并發(fā)舶得,也就是說同時(shí)接待客戶的能力。(場地大忻峙啊)

所以ajax輪詢和long poll都有可能發(fā)生這種情況扩灯。

客戶端:啦啦啦啦,有新信息么霜瘪?

服務(wù)端:月線正忙珠插,請稍后再試(503 Server Unavailable)

客戶端:。颖对。捻撑。。好吧缤底,啦啦啦顾患,有新信息么?

服務(wù)端:月線正忙个唧,請稍后再試(503 Server Unavailable)

客戶端:然后服務(wù)端在一旁忙的要死:冰箱江解,我要更多的冰箱!更多徙歼。犁河。更多。魄梯。(我錯(cuò)了桨螺。。這又是梗酿秸。灭翔。)

言歸正傳,我們來說Websocket吧

通過上面這個(gè)例子辣苏,我們可以看出肝箱,這兩種方式都不是最好的方式哄褒,需要很多資源。

一種需要更快的速度狭园,一種需要更多的’電話’读处。這兩種都會導(dǎo)致’電話’的需求越來越高。

哦對了唱矛,忘記說了HTTP還是一個(gè)狀態(tài)協(xié)議。

通俗的說就是井辜,服務(wù)器因?yàn)槊刻煲哟嗫蛻袅艘锴莻€(gè)健忘鬼,你一掛電話粥脚,他就把你的東西全忘光了窃肠,把你的東西全丟掉了。你第二次還得再告訴服務(wù)器一遍刷允。

所以在這種情況下出現(xiàn)了冤留,Websocket出現(xiàn)了。他解決了HTTP的這幾個(gè)難題树灶。首先纤怒,被動(dòng)性,當(dāng)服務(wù)器完成協(xié)議升級后(HTTP->Websocket)天通,服務(wù)端就可以主動(dòng)推送信息給客戶端啦泊窘。所以上面的情景可以做如下修改。

客戶端:啦啦啦像寒,我要建立Websocket協(xié)議烘豹,需要的服務(wù):chat,Websocket協(xié)議版本:17(HTTP Request)

服務(wù)端:ok诺祸,確認(rèn)携悯,已升級為Websocket協(xié)議(HTTP Protocols Switched)

客戶端:麻煩你有信息的時(shí)候推送給我噢。筷笨。

服務(wù)端:ok憔鬼,有的時(shí)候會告訴你的。

服務(wù)端:balabalabalabala

服務(wù)端:balabalabalabala

服務(wù)端:哈哈哈哈哈啊哈哈哈哈

服務(wù)端:笑死我了哈哈哈哈哈哈哈

就變成了這樣奥秆,只需要經(jīng)過一次HTTP請求逊彭,就可以做到源源不斷的信息傳送了。(在程序設(shè)計(jì)中构订,這種設(shè)計(jì)叫做回調(diào)侮叮,即:你有信息了再來通知我,而不是我傻乎乎的每次跑來問你?)

這樣的協(xié)議解決了上面同步有延遲悼瘾,而且還非常消耗資源的這種情況囊榜。那么為什么他會解決服務(wù)器上消耗資源的問題呢审胸?

其實(shí)我們所用的程序是要經(jīng)過兩層代理的,即HTTP協(xié)議在Nginx等服務(wù)器的解析下卸勺,然后再傳送給相應(yīng)的Handler(PHP等)來處理砂沛。簡單地說,我們有一個(gè)非呈锴螅快速的接線員(Nginx)碍庵,他負(fù)責(zé)把問題轉(zhuǎn)交給相應(yīng)的客服(Handler)。

本身接線員基本上速度是足夠的悟狱,但是每次都卡在客服(Handler)了静浴,老有客服處理速度太慢。挤渐,導(dǎo)致客服不夠苹享。Websocket就解決了這樣一個(gè)難題,建立后浴麻,可以直接跟接線員建立持久連接得问,有信息的時(shí)候客服想辦法通知接線員,然后接線員在統(tǒng)一轉(zhuǎn)交給客戶软免。

這樣就可以解決客服處理速度過慢的問題了宫纬。

同時(shí),在傳統(tǒng)的方式上或杠,要不斷的建立哪怔,關(guān)閉HTTP協(xié)議,由于HTTP是非狀態(tài)性的向抢,每次都要重新傳輸identity info(鑒別信息)认境,來告訴服務(wù)端你是誰。

雖然接線員很快速挟鸠,但是每次都要聽這么一堆叉信,效率也會有所下降的,同時(shí)還得不斷把這些信息轉(zhuǎn)交給客服艘希,不但浪費(fèi)客服的處理時(shí)間硼身,而且還會在網(wǎng)路傳輸中消耗過多的流量/時(shí)間。

但是Websocket只需要一次HTTP握手覆享,所以說整個(gè)通訊過程是建立在一次連接/狀態(tài)中佳遂,也就避免了HTTP的非狀態(tài)性,服務(wù)端會一直知道你的信息撒顿,直到你關(guān)閉請求丑罪,這樣就解決了接線員要反復(fù)解析HTTP協(xié)議,還要查看identity info的信息。

同時(shí)由客戶主動(dòng)詢問吩屹,轉(zhuǎn)換為服務(wù)器(推送)有信息的時(shí)候就發(fā)送(當(dāng)然客戶端還是等主動(dòng)發(fā)送信息過來的跪另。。)煤搜,沒有信息的時(shí)候就交給接線員(Nginx)免绿,不需要占用本身速度就慢的客服(Handler)了

——————–

至于怎么在不支持Websocket的客戶端上使用Websocket。擦盾。答案是:不能

但是可以通過上面說的long poll和ajax 輪詢來 模擬出類似的效果

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘲驾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子厌衙,更是在濱河造成了極大的恐慌距淫,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件婶希,死亡現(xiàn)場離奇詭異,居然都是意外死亡蓬衡,警方通過查閱死者的電腦和手機(jī)喻杈,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來狰晚,“玉大人筒饰,你說我怎么就攤上這事”谏梗” “怎么了瓷们?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長秒咐。 經(jīng)常有香客問我谬晕,道長,這世上最難降的妖魔是什么携取? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任攒钳,我火速辦了婚禮,結(jié)果婚禮上雷滋,老公的妹妹穿的比我還像新娘不撑。我一直安慰自己,他們只是感情好晤斩,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布焕檬。 她就那樣靜靜地躺著,像睡著了一般澳泵。 火紅的嫁衣襯著肌膚如雪实愚。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天,我揣著相機(jī)與錄音爆侣,去河邊找鬼萍程。 笑死,一個(gè)胖子當(dāng)著我的面吹牛兔仰,可吹牛的內(nèi)容都是我干的茫负。 我是一名探鬼主播,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼乎赴,長吁一口氣:“原來是場噩夢啊……” “哼忍法!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起榕吼,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤饿序,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后羹蚣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體原探,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年顽素,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咽弦。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,865評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胁出,死狀恐怖型型,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情全蝶,我是刑警寧澤闹蒜,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站抑淫,受9級特大地震影響绷落,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丈冬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一嘱函、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧埂蕊,春花似錦往弓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喉童,卻和暖如春撇寞,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工蔑担, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牌废,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓啤握,卻偏偏與公主長得像鸟缕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子排抬,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,870評論 2 361

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