一誉结、websocket與http
WebSocket是HTML5出的東西(協(xié)議)鹅士,也就是說HTTP協(xié)議沒有變化,或者說沒關(guān)系惩坑,但HTTP是不支持持久連接的(長連接掉盅,循環(huán)連接的不算)
首先HTTP有1.1和1.0之說,也就是所謂的keep-alive以舒,把多個(gè)HTTP請(qǐng)求合并為一個(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ù),就是這樣=臀玄。=
再簡單來說瓢阴,層級(jí)不一樣。
二镐牺、Websocket是什么樣的協(xié)議炫掐,具體有什么優(yōu)點(diǎn)
首先魁莉,Websocket是一個(gè)持久化的協(xié)議睬涧,相對(duì)于HTTP這種非持久的協(xié)議來說。簡單的舉個(gè)例子吧旗唁,用目前應(yīng)用比較廣泛的PHP生命周期來解釋畦浓。
HTTP的生命周期通過Request來界定,也就是一個(gè)Request一個(gè)Response检疫,那么在HTTP1.0中讶请,這次HTTP請(qǐng)求就結(jié)束了。
在HTTP1.1中進(jìn)行了改進(jìn),使得有一個(gè)keep-alive夺溢,也就是說论巍,在一個(gè)HTTP連接中,可以發(fā)送多個(gè)Request风响,接收多個(gè)Response嘉汰。但是請(qǐng)記住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.1Host:server.example.comUpgrade:websocketConnection:UpgradeSec-WebSocket-Key:x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol:chat, superchatSec-WebSocket-Version:13Origin:http://example.com
熟悉HTTP的童鞋可能發(fā)現(xiàn)了,這段類似HTTP協(xié)議的握手請(qǐng)求中钱反,多了幾個(gè)東西掖看。我會(huì)順便講解下作用。
Upgrade:websocketConnection:Upgrade
這個(gè)就是Websocket的核心了面哥,告訴Apache哎壳、Nginx等服務(wù)器:注意啦,我發(fā)起的是Websocket協(xié)議尚卫,快點(diǎn)幫我找到對(duì)應(yīng)的助理處理~不是那個(gè)老土的HTTP归榕。
Sec-WebSocket-Key:x3JJHMbDL1EzLkh9GBhXDw==Sec-WebSocket-Protocol:chat, superchatSec-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ù)器會(huì)返回下列東西,表示已經(jīng)接受到請(qǐng)求闪彼, 成功建立Websocket啦甜孤!
HTTP/1.1101 Switching ProtocolsUpgrade:websocketConnection:UpgradeSec-WebSocket-Accept:HSmrc0sMlYUkAGmm5OPpG2HaGWk=Sec-WebSocket-Protocol:chat
這里開始就是HTTP最后負(fù)責(zé)的區(qū)域了,告訴客戶畏腕,我已經(jīng)成功切換協(xié)議啦~
Upgrade:websocketConnection:Upgrade
依然是固定的缴川,告訴客戶端即將升級(jí)的是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ā)送一次請(qǐng)求,詢問服務(wù)器是否有新信息秃症。
場(chǎng)景再現(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ù)始睦疫。
場(chǎng)景再現(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è)梗)(不會(huì)、不能主動(dòng)發(fā)起連接)庇绽,但是上司有命令锡搜,如果有客戶來,不管多么累都要好好接待瞧掺。
說完這個(gè)耕餐,我們?cè)賮碚f一說上面的缺陷(原諒我廢話這么多吧OAQ)
從上面很容易看出來,不管怎么樣辟狈,上面這兩種都是非常消耗資源的肠缔。
ajax輪詢 需要服務(wù)器有很快的處理速度和資源。(速度)long poll 需要有很高的并發(fā)哼转,也就是說同時(shí)接待客戶的能力明未。(場(chǎng)地大小)
所以ajax輪詢和long poll都有可能發(fā)生這種情況壹蔓。
客戶端:啦啦啦啦趟妥,有新信息么?
服務(wù)端:月線正忙佣蓉,請(qǐng)稍后再試(503 Server Unavailable)
客戶端:披摄。亲雪。。行疏。好吧匆光,啦啦啦套像,有新信息么酿联?
服務(wù)端:月線正忙,請(qǐng)稍后再試(503 Server Unavailable)
客戶端:然后服務(wù)端在一旁忙的要死:冰箱夺巩,我要更多的冰箱贞让!更多。柳譬。更多喳张。。(我錯(cuò)了美澳。销部。這又是梗。制跟。)
言歸正傳舅桩,我們來說Websocket吧
通過上面這個(gè)例子,我們可以看出雨膨,這兩種方式都不是最好的方式擂涛,需要很多資源。
一種需要更快的速度聊记,一種需要更多的’電話’撒妈。這兩種都會(huì)導(dǎo)致’電話’的需求越來越高。
哦對(duì)了排监,忘記說了HTTP還是一個(gè)狀態(tài)協(xié)議狰右。
通俗的說就是,服務(wù)器因?yàn)槊刻煲哟嗫蛻袅擞叽玻莻€(gè)健忘鬼挟阻,你一掛電話,他就把你的東西全忘光了峭弟,把你的東西全丟掉了附鸽。你第二次還得再告訴服務(wù)器一遍。
所以在這種情況下出現(xiàn)了瞒瘸,Websocket出現(xiàn)了坷备。他解決了HTTP的這幾個(gè)難題。首先情臭,被動(dòng)性省撑,當(dāng)服務(wù)器完成協(xié)議升級(jí)后(HTTP->Websocket)赌蔑,服務(wù)端就可以主動(dòng)推送信息給客戶端啦。所以上面的情景可以做如下修改竟秫。
客戶端:啦啦啦娃惯,我要建立Websocket協(xié)議,需要的服務(wù):chat肥败,Websocket協(xié)議版本:17(HTTP Request)
服務(wù)端:ok趾浅,確認(rèn),已升級(jí)為Websocket協(xié)議(HTTP Protocols Switched)
客戶端:麻煩你有信息的時(shí)候推送給我噢馒稍。皿哨。
服務(wù)端:ok,有的時(shí)候會(huì)告訴你的纽谒。
服務(wù)端:balabalabalabala
服務(wù)端:balabalabalabala
服務(wù)端:哈哈哈哈哈啊哈哈哈哈
服務(wù)端:笑死我了哈哈哈哈哈哈哈
就變成了這樣证膨,只需要經(jīng)過一次HTTP請(qǐng)求,就可以做到源源不斷的信息傳送了鼓黔。(在程序設(shè)計(jì)中央勒,這種設(shè)計(jì)叫做回調(diào),即:你有信息了再來通知我澳化,而不是我傻乎乎的每次跑來問你?)
這樣的協(xié)議解決了上面同步有延遲崔步,而且還非常消耗資源的這種情況。那么為什么他會(huì)解決服務(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ù)端你是誰语淘。
雖然接線員很快速诲宇,但是每次都要聽這么一堆,效率也會(huì)有所下降的亏娜,同時(shí)還得不斷把這些信息轉(zhuǎn)交給客服焕窝,不但浪費(fèi)客服的處理時(shí)間蹬挺,而且還會(huì)在網(wǎng)路傳輸中消耗過多的流量/時(shí)間维贺。
但是Websocket只需要一次HTTP握手,所以說整個(gè)通訊過程是建立在一次連接/狀態(tài)中巴帮,也就避免了HTTP的非狀態(tài)性溯泣,服務(wù)端會(huì)一直知道你的信息,直到你關(guān)閉請(qǐng)求榕茧,這樣就解決了接線員要反復(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 輪詢來 模擬出類似的效果