websocket 協(xié)議理解 來自知乎回帖

先粘貼上一個知乎回帖捐晶,說的很清晰伸刃,語言也萌萌噠 看完會感覺豁然開朗拢军,下面是正文:

一、websocket與http

WebSocket是HTML5出的東西(協(xié)議)送巡,也就是說HTTP協(xié)議沒有變化摹菠,或者說沒關系,但HTTP是不支持持久連接的(長連接骗爆,循環(huán)連接的不算)

首先HTTP有1.1和1.0之說次氨,也就是所謂的keep-alive,把多個HTTP請求合并為一個摘投,但是Websocket其實是一個新協(xié)議煮寡,跟HTTP協(xié)議基本沒有關系,只是為了兼容現有瀏覽器的握手規(guī)范而已犀呼,也就是說它是HTTP協(xié)議上的一種補充可以通過這樣一張圖理解

有交集幸撕,但是并不是全部。

另外html5是指的一系列新的API外臂,或者說新規(guī)范坐儿,新技術。Http協(xié)議本身只有1.0和1.1宋光,而且跟Html本身沒有直接關系貌矿。。通俗來說罪佳,你可以用HTTP協(xié)議傳輸非Html數據逛漫,就是這樣=。=

再簡單來說赘艳,層級不一樣酌毡。

二、Websocket是什么樣的協(xié)議第练,具體有什么優(yōu)點

首先阔馋,Websocket是一個持久化的協(xié)議玛荞,相對于HTTP這種非持久的協(xié)議來說娇掏。簡單的舉個例子吧,用目前應用比較廣泛的PHP生命周期來解釋勋眯。

HTTP的生命周期通過Request來界定婴梧,也就是一個Request一個Response下梢,那么在HTTP1.0中,這次HTTP請求就結束了塞蹭。

在HTTP1.1中進行了改進孽江,使得有一個keep-alive,也就是說番电,在一個HTTP連接中岗屏,可以發(fā)送多個Request,接收多個Response漱办。但是請記住Request = Response这刷, 在HTTP中永遠是這樣,也就是說一個request只能有一個response娩井。而且這個response也是被動的暇屋,不能主動發(fā)起。

教練洞辣,你BB了這么多咐刨,跟Websocket有什么關系呢?_(:з」∠)_好吧扬霜,我正準備說Websocket呢定鸟。。

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

首先我們來看個典型的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ā)現了躯泰,這段類似HTTP協(xié)議的握手請求中,多了幾個東西华糖。我會順便講解下作用麦向。

Upgrade: websocket

Connection: Upgrade

這個就是Websocket的核心了,告訴Apache客叉、Nginx等服務器:注意啦诵竭,我發(fā)起的是Websocket協(xié)議,快點幫我找到對應的助理處理~不是那個老土的HTTP兼搏。

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==

Sec-WebSocket-Protocol: chat, superchat

Sec-WebSocket-Version: 13

首先卵慰,Sec-WebSocket-Key是一個Base64 encode的值,這個是瀏覽器隨機生成的佛呻,告訴服務器:泥煤裳朋,不要忽悠窩,我要驗證尼是不是真的是Websocket助理吓著。

然后鲤嫡,Sec_WebSocket-Protocol是一個用戶定義的字符串送挑,用來區(qū)分同URL下,不同的服務所需要的協(xié)議暖眼。簡單理解:今晚我要服務A惕耕,別搞錯啦~

最后,Sec-WebSocket-Version是告訴服務器所使用的Websocket Draft(協(xié)議版本)诫肠,在最初的時候司澎,Websocket協(xié)議還在Draft階段,各種奇奇怪怪的協(xié)議都有栋豫,而且還有很多期奇奇怪怪不同的東西惭缰,什么Firefox和Chrome用的不是一個版本之類的,當初Websocket協(xié)議太多可是一個大難題笼才。漱受。不過現在還好,已經定下來啦~大家都使用的一個東西~ 脫水:服務員骡送,我要的是13歲的噢→_→

然后服務器會返回下列東西昂羡,表示已經接受到請求, 成功建立Websocket啦摔踱!

HTTP/1.1 101 Switching Protocols

Upgrade: websocket

Connection: Upgrade

Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=

Sec-WebSocket-Protocol: chat

這里開始就是HTTP最后負責的區(qū)域了虐先,告訴客戶,我已經成功切換協(xié)議啦~

Upgrade: websocket

Connection: Upgrade

依然是固定的派敷,告訴客戶端即將升級的是Websocket協(xié)議蛹批,而不是mozillasocket,lurnarsocket或者shitsocket篮愉。

然后腐芍,Sec-WebSocket-Accept這個則是經過服務器確認,并且加密過后的Sec-WebSocket-Key试躏。?服務器:好啦好啦猪勇,知道啦,給你看我的ID CARD來證明行了吧颠蕴。泣刹。

后面的,Sec-WebSocket-Protocol則是表示最終使用的協(xié)議犀被。

至此椅您,HTTP已經完成它所有工作了,接下來就是完全按照Websocket協(xié)議進行了寡键。具體的協(xié)議就不在這闡述了掀泳。

——————技術解析部分完畢——————

你TMD又BBB了這么久,那到底Websocket有什么鬼用,http long poll开伏,或者ajax輪詢不都可以實現實時信息傳遞么膀跌。

好好好遭商,年輕人固灵,那我們來講一講Websocket有什么用。來給你吃點胡(蘇)蘿(丹)卜(紅)

三劫流、Websocket的作用

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

ajax輪詢

ajax輪詢的原理非常簡單祠汇,讓瀏覽器隔個幾秒就發(fā)送一次請求仍秤,詢問服務器是否有新信息。

場景再現:

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

服務端:沒有(Response)

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

服務端:沒有。我抠。(Response)

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

服務端:你好煩啊,沒有啊菜拓。瓣窄。(Response)

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

服務端:好啦好啦纳鼎,有啦給你俺夕。(Response)

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

服務端:贱鄙。劝贸。。逗宁。悬荣。沒。疙剑。氯迂。。沒言缤。嚼蚀。。沒有(Response) —- loop

long poll

long poll其實原理跟ajax輪詢差不多管挟,都是采用輪詢的方式轿曙,不過采取的是阻塞模型(一直打電話,沒收到就不掛電話),也就是說导帝,客戶端發(fā)起連接后守谓,如果沒消息,就一直不返回Response給客戶端您单。直到有消息才返回斋荞,返回完之后,客戶端再次建立連接虐秦,周而復始平酿。

場景再現:

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

服務端:額蜈彼。。 等待到有消息的時候俺驶。幸逆。來 給你(Response)

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

從上面可以看出其實這兩種方式还绘,都是在不斷地建立HTTP連接,然后等待服務端處理送矩,可以體現HTTP協(xié)議的另外一個特點蚕甥,被動性。

何為被動性呢栋荸,其實就是菇怀,服務端不能主動聯(lián)系客戶端,只能有客戶端發(fā)起晌块。

簡單地說就是爱沟,服務器是一個很懶的冰箱(這是個梗)(不會、不能主動發(fā)起連接)匆背,但是上司有命令呼伸,如果有客戶來,不管多么累都要好好接待钝尸。

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

從上面很容易看出來,不管怎么樣珍促,上面這兩種都是非常消耗資源的铃辖。

ajax輪詢 需要服務器有很快的處理速度和資源。(速度)long poll 需要有很高的并發(fā)猪叙,也就是說同時接待客戶的能力娇斩。(場地大腥示怼)

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

客戶端:啦啦啦啦犬第,有新信息么锦积?

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

客戶端:歉嗓。丰介。。遥椿。好吧基矮,啦啦啦淆储,有新信息么冠场?

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

客戶端:然后服務端在一旁忙的要死:冰箱本砰,我要更多的冰箱碴裙!更多点额。。更多还棱。。(我錯了珍手。办铡。這又是梗。琳要。)

言歸正傳,我們來說Websocket吧

通過上面這個例子稚补,我們可以看出,這兩種方式都不是最好的方式课幕,需要很多資源厦坛。

一種需要更快的速度,一種需要更多的’電話’乍惊。這兩種都會導致’電話’的需求越來越高。

哦對了污桦,忘記說了HTTP還是一個狀態(tài)協(xié)議匙监。

通俗的說就是小作,服務器因為每天要接待太多客戶了,是個健忘鬼顾稀,你一掛電話,他就把你的東西全忘光了静秆,把你的東西全丟掉了。你第二次還得再告訴服務器一遍抚笔。

所以在這種情況下出現了,Websocket出現了辐宾。他解決了HTTP的這幾個難題膨蛮。首先,被動性敞葛,當服務器完成協(xié)議升級后(HTTP->Websocket),服務端就可以主動推送信息給客戶端啦惹谐。所以上面的情景可以做如下修改。

客戶端:啦啦啦综液,我要建立Websocket協(xié)議儒飒,需要的服務:chat,Websocket協(xié)議版本:17(HTTP Request)

服務端:ok桩了,確認附帽,已升級為Websocket協(xié)議(HTTP Protocols Switched)

客戶端:麻煩你有信息的時候推送給我噢。井誉。

服務端:ok,有的時候會告訴你的颗圣。

服務端:balabalabalabala

服務端:balabalabalabala

服務端:哈哈哈哈哈啊哈哈哈哈

服務端:笑死我了哈哈哈哈哈哈哈

就變成了這樣屁使,只需要經過一次HTTP請求奔则,就可以做到源源不斷的信息傳送了。(在程序設計中酬蹋,這種設計叫做回調抽莱,即:你有信息了再來通知我范抓,而不是我傻乎乎的每次跑來問你?)

這樣的協(xié)議解決了上面同步有延遲食铐,而且還非常消耗資源的這種情況。那么為什么他會解決服務器上消耗資源的問題呢年缎?

其實我們所用的程序是要經過兩層代理的铃慷,即HTTP協(xié)議在Nginx等服務器的解析下蜕该,然后再傳送給相應的Handler(php等)來處理。簡單地說堂淡,我們有一個非常快速的接線員(Nginx)萤悴,他負責把問題轉交給相應的客服(Handler)皆的。

本身接線員基本上速度是足夠的,但是每次都卡在客服(Handler)了费薄,老有客服處理速度太慢。伟众,導致客服不夠召廷。Websocket就解決了這樣一個難題账胧,建立后先紫,可以直接跟接線員建立持久連接,有信息的時候客服想辦法通知接線員泡孩,然后接線員在統(tǒng)一轉交給客戶。

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

同時眼俊,在傳統(tǒng)的方式上,要不斷的建立疮胖,關閉HTTP協(xié)議,由于HTTP是非狀態(tài)性的院塞,每次都要重新傳輸identity info(鑒別信息)性昭,來告訴服務端你是誰。

雖然接線員很快速糜颠,但是每次都要聽這么一堆,效率也會有所下降的顶瞒,同時還得不斷把這些信息轉交給客服元旬,不但浪費客服的處理時間,而且還會在網路傳輸中消耗過多的流量/時間法绵。

但是Websocket只需要一次HTTP握手青责,所以說整個通訊過程是建立在一次連接/狀態(tài)中肤视,也就避免了HTTP的非狀態(tài)性字柠,服務端會一直知道你的信息窑业,直到你關閉請求,這樣就解決了接線員要反復解析HTTP協(xié)議鲤氢,還要查看identity info的信息西潘。

同時由客戶主動詢問,轉換為服務器(推送)有信息的時候就發(fā)送(當然客戶端還是等主動發(fā)送信息過來的喷市。。)寝并,沒有信息的時候就交給接線員(Nginx)腹备,不需要占用本身速度就慢的客服(Handler)了

——————–

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

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


喵喵喵 (`?ω?′)好啦,正文結束,這篇文章我看了感覺很好喇伯,不知道有沒有幫助到大家呢,話說回帖的人說話好萌好有趣艾猜,我感覺是個妹子呢捻悯,看人家妹子那么厲害,我還是個小渣渣今缚,我要加油了?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末姓言,一起剝皮案震驚了整個濱河市蔗蹋,隨后出現的幾起案子囱淋,更是在濱河造成了極大的恐慌,老刑警劉巖妥衣,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件税手,死亡現場離奇詭異,居然都是意外死亡冈止,警方通過查閱死者的電腦和手機,發(fā)現死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門闺属,熙熙樓的掌柜王于貴愁眉苦臉地迎上來周霉,“玉大人,你說我怎么就攤上這事国瓮∧祝” “怎么了?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵孵睬,是天一觀的道長伶跷。 經常有香客問我,道長叭莫,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任拢肆,我火速辦了婚禮,結果婚禮上辩蛋,老公的妹妹穿的比我還像新娘移盆。我一直安慰自己,他們只是感情好咒循,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著颖医,像睡著了一般裆蒸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上僚祷,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天辙谜,我揣著相機與錄音,去河邊找鬼装哆。 笑死,一個胖子當著我的面吹牛萍桌,可吹牛的內容都是我干的奸绷。 我是一名探鬼主播,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼号醉,長吁一口氣:“原來是場噩夢啊……” “哼畔派!你這毒婦竟也來了润绵?” 一聲冷哼從身側響起线椰,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤憨愉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后配紫,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡享扔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年惧眠,在試婚紗的時候發(fā)現自己被綠了于个。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡厅篓,死狀恐怖,靈堂內的尸體忽然破棺而出应又,到底是詐尸還是另有隱情乏苦,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布洞就,位于F島的核電站掀淘,受9級特大地震影響旬蟋,放射性物質發(fā)生泄漏革娄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一匆浙、第九天 我趴在偏房一處隱蔽的房頂上張望厕妖。 院中可真熱鬧,春花似錦软能、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽范舀。三九已至了罪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間泊藕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工玫锋, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留讼呢,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓节沦,卻偏偏與公主長得像础爬,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子看蚜,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

推薦閱讀更多精彩內容