溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Websocket原理

發(fā)布時(shí)間:2020-07-05 23:53:19 來(lái)源:網(wǎng)絡(luò) 閱讀:571 作者:new個(gè)對(duì)象 欄目:開發(fā)技術(shù)

一、websocket與http
WebSocket是HTML5出的東西(協(xié)議),也就是說(shuō)HTTP協(xié)議沒(méi)有變化,或者說(shuō)沒(méi)關(guān)系,但HTTP是不支持持久連接的(長(zhǎng)連接,循環(huán)連接的不算)
首先HTTP有 1.1 和 1.0 之說(shuō),也就是所謂的 keep-alive ,把多個(gè)HTTP請(qǐng)求合并為一個(gè),但是 Websocket 其實(shí)是一個(gè)新協(xié)議,跟HTTP協(xié)議基本沒(méi)有關(guān)系,只是為了兼容現(xiàn)有瀏覽器的握手規(guī)范而已,也就是說(shuō)它是HTTP協(xié)議上的一種補(bǔ)充可以通過(guò)這樣一張圖理解,有交集,但是并不是全部。
另外Html5是指的一系列新的API,或者說(shuō)新規(guī)范,新技術(shù)。Http協(xié)議本身只有1.0和1.1,而且跟Html本身沒(méi)有直接關(guān)系。。通俗來(lái)說(shuō),你可以用HTTP協(xié)議傳輸非Html數(shù)據(jù),就是這樣=。=
再簡(jiǎn)單來(lái)說(shuō),層級(jí)不一樣。
二、Websocket是什么樣的協(xié)議,具體有什么優(yōu)點(diǎn)
首先,Websocket是一個(gè)持久化的協(xié)議,相對(duì)于HTTP這種非持久的協(xié)議來(lái)說(shuō)。簡(jiǎn)單的舉個(gè)例子吧,用目前應(yīng)用比較廣泛的PHP生命周期來(lái)解釋。
HTTP的生命周期通過(guò) Request 來(lái)界定,也就是一個(gè) Request 一個(gè) Response ,那么在 HTTP1.0 中,這次HTTP請(qǐng)求就結(jié)束了。
在HTTP1.1中進(jìn)行了改進(jìn),使得有一個(gè)keep-alive,也就是說(shuō),在一個(gè)HTTP連接中,可以發(fā)送多個(gè)Request,接收多個(gè)Response。但是請(qǐng)記住 Request = Response , 在HTTP中永遠(yuǎn)是這樣,也就是說(shuō)一個(gè)request只能有一個(gè)response。而且這個(gè)response也是被動(dòng)的,不能主動(dòng)發(fā)起。
教練,你BB了這么多,跟Websocket有什么關(guān)系呢?_(:з」∠)_好吧,我正準(zhǔn)備說(shuō)Websocket呢。。
首先Websocket是基于HTTP協(xié)議的,或者說(shuō)借用了HTTP的協(xié)議來(lái)完成一部分握手。
首先我們來(lái)看個(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é)議的握手請(qǐng)求中,多了幾個(gè)東西。我會(huì)順便講解下作用。
Upgrade: websocket
Connection: Upgrade
這個(gè)就是Websocket的核心了,告訴 Apache 、 Nginx 等服務(wù)器:注意啦,我發(fā)起的是Websocket協(xié)議,快點(diǎn)幫我找到對(duì)應(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助理。
然后, SecWebSocket-Protocol 是一個(gè)用戶定義的字符串,用來(lái)區(qū)分同URL下,不同的服務(wù)所需要的協(xié)議。簡(jiǎn)單理解:今晚我要服務(wù)A,別搞錯(cuò)啦~
最后, Sec-WebSocket-Version 是告訴服務(wù)器所使用的 Websocket Draft(協(xié)議版本),在最初的時(shí)候,Websocket協(xié)議還在 Draft 階段,各種奇奇怪怪的協(xié)議都有,而且還有很多期奇奇怪怪不同的東西,什么Firefox和Chrome用的不是一個(gè)版本之類的,當(dāng)初Websocket協(xié)議太多可是一個(gè)大難題。。不過(guò)現(xiàn)在還好,已經(jīng)定下來(lái)啦~大家都使用的一個(gè)東西~ 脫水: 服務(wù)員,我要的是13歲的噢→

然后服務(wù)器會(huì)返回下列東西,表示已經(jīng)接受到請(qǐ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
依然是固定的,告訴客戶端即將升級(jí)的是 Websocket 協(xié)議,而不是mozillasocket,lurnarsocket或者shitsocket。
然后, Sec-WebSocket-Accept 這個(gè)則是經(jīng)過(guò)服務(wù)器確認(rèn),并且加密過(guò)后的 Sec-WebSocket-Key 。 服務(wù)器:好啦好啦,知道啦,給你看我的ID CARD來(lái)證明行了吧。。
后面的, Sec-WebSocket-Protocol 則是表示最終使用的協(xié)議。
至此,HTTP已經(jīng)完成它所有工作了,接下來(lái)就是完全按照Websocket協(xié)議進(jìn)行了。具體的協(xié)議就不在這闡述了。
——————技術(shù)解析部分完畢——————
三、Websocket的作用
在講Websocket之前,我就順帶著講下 long poll 和 ajax輪詢 的原理。
ajax輪詢
ajax輪詢的原理非常簡(jiǎn)單,讓瀏覽器隔個(gè)幾秒就發(fā)送一次請(qǐng)求,詢問(wèn)服務(wù)器是否有新信息。
場(chǎng)景再現(xiàn):
客戶端:啦啦啦,有沒(méi)有新信息(Request)
服務(wù)端:沒(méi)有(Response)
客戶端:啦啦啦,有沒(méi)有新信息(Request)
服務(wù)端:沒(méi)有。。(Response)
客戶端:啦啦啦,有沒(méi)有新信息(Request)
服務(wù)端:你好煩啊,沒(méi)有啊。。(Response)
客戶端:啦啦啦,有沒(méi)有新消息(Request)
服務(wù)端:好啦好啦,有啦給你。(Response)
客戶端:啦啦啦,有沒(méi)有新消息(Request)
服務(wù)端:。。。。。沒(méi)。。。。沒(méi)。。。沒(méi)有(Response) —- loop
long poll
long poll 其實(shí)原理跟 ajax輪詢 差不多,都是采用輪詢的方式,不過(guò)采取的是阻塞模型(一直打電話,沒(méi)收到就不掛電話),也就是說(shuō),客戶端發(fā)起連接后,如果沒(méi)消息,就一直不返回Response給客戶端。直到有消息才返回,返回完之后,客戶端再次建立連接,周而復(fù)始。
場(chǎng)景再現(xiàn):
客戶端:啦啦啦,有沒(méi)有新信息,沒(méi)有的話就等有了才返回給我吧(Request)
服務(wù)端:額。。 等待到有消息的時(shí)候。。來(lái) 給你(Response)
客戶端:啦啦啦,有沒(méi)有新信息,沒(méi)有的話就等有了才返回給我吧(Request) -loop
從上面可以看出其實(shí)這兩種方式,都是在不斷地建立HTTP連接,然后等待服務(wù)端處理,可以體現(xiàn)HTTP協(xié)議的另外一個(gè)特點(diǎn),被動(dòng)性。
何為被動(dòng)性呢,其實(shí)就是,服務(wù)端不能主動(dòng)聯(lián)系客戶端,只能有客戶端發(fā)起。
簡(jiǎn)單地說(shuō)就是,服務(wù)器是一個(gè)很懶的冰箱(這是個(gè)梗)(不會(huì)、不能主動(dòng)發(fā)起連接),但是上司有命令,如果有客戶來(lái),不管多么累都要好好接待。
說(shuō)完這個(gè),我們?cè)賮?lái)說(shuō)一說(shuō)上面的缺陷(原諒我廢話這么多吧OAQ)
從上面很容易看出來(lái),不管怎么樣,上面這兩種都是非常消耗資源的。
ajax輪詢 需要服務(wù)器有很快的處理速度和資源。(速度)long poll 需要有很高的并發(fā),也就是說(shuō)同時(shí)接待客戶的能力。(場(chǎng)地大?。?br/>所以 ajax輪詢 和 long poll 都有可能發(fā)生這種情況。
客戶端:啦啦啦啦,有新信息么?
服務(wù)端:月線正忙,請(qǐng)稍后再試(503 Server Unavailable)
客戶端:。。。。好吧,啦啦啦,有新信息么?
服務(wù)端:月線正忙,請(qǐng)稍后再試(503 Server Unavailable)
客戶端:然后服務(wù)端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。(我錯(cuò)了。。這又是梗。。)
言歸正傳,我們來(lái)說(shuō)Websocket吧
通過(guò)上面這個(gè)例子,我們可以看出,這兩種方式都不是最好的方式,需要很多資源。
一種需要更快的速度,一種需要更多的’電話’。這兩種都會(huì)導(dǎo)致’電話’的需求越來(lái)越高。
哦對(duì)了,忘記說(shuō)了HTTP還是一個(gè)狀態(tài)協(xié)議。
通俗的說(shuō)就是,服務(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)過(guò)一次HTTP請(qǐng)求,就可以做到源源不斷的信息傳送了。(在程序設(shè)計(jì)中,這種設(shè)計(jì)叫做回調(diào),即:你有信息了再來(lái)通知我,而不是我傻乎乎的每次跑來(lái)問(wèn)你 )
這樣的協(xié)議解決了上面同步有延遲,而且還非常消耗資源的這種情況。那么為什么他會(huì)解決服務(wù)器上消耗資源的問(wèn)題呢?
其實(shí)我們所用的程序是要經(jīng)過(guò)兩層代理的,即HTTP協(xié)議在Nginx等服務(wù)器的解析下,然后再傳送給相應(yīng)的Handler(PHP等)來(lái)處理。簡(jiǎn)單地說(shuō),我們有一個(gè)非??焖俚?接線員(Nginx) ,他負(fù)責(zé)把問(wèn)題轉(zhuǎn)交給相應(yīng)的 客服(Handler) 。
本身接線員基本上速度是足夠的,但是每次都卡在客服(Handler)了,老有客服處理速度太慢。,導(dǎo)致客服不夠。Websocket就解決了這樣一個(gè)難題,建立后,可以直接跟接線員建立持久連接,有信息的時(shí)候客服想辦法通知接線員,然后接線員在統(tǒng)一轉(zhuǎn)交給客戶。
這樣就可以解決客服處理速度過(guò)慢的問(wèn)題了。
同時(shí),在傳統(tǒng)的方式上,要不斷的建立,關(guān)閉HTTP協(xié)議,由于HTTP是非狀態(tài)性的,每次都要重新傳輸 identity info (鑒別信息),來(lái)告訴服務(wù)端你是誰(shuí)。
雖然接線員很快速,但是每次都要聽這么一堆,效率也會(huì)有所下降的,同時(shí)還得不斷把這些信息轉(zhuǎn)交給客服,不但浪費(fèi)客服的處理時(shí)間,而且還會(huì)在網(wǎng)路傳輸中消耗過(guò)多的流量/時(shí)間。
但是Websocket只需要一次HTTP握手,所以說(shuō)整個(gè)通訊過(guò)程是建立在一次連接/狀態(tài)中,也就避免了HTTP的非狀態(tài)性,服務(wù)端會(huì)一直知道你的信息,直到你關(guān)閉請(qǐng)求,這樣就解決了接線員要反復(fù)解析HTTP協(xié)議,還要查看identity info的信息。
同時(shí)由客戶主動(dòng)詢問(wèn),轉(zhuǎn)換為服務(wù)器(推送)有信息的時(shí)候就發(fā)送(當(dāng)然客戶端還是等主動(dòng)發(fā)送信息過(guò)來(lái)的。。),沒(méi)有信息的時(shí)候就交給接線員(Nginx),不需要占用本身速度就慢的客服(Handler)了
——————–
至于怎么在不支持Websocket的客戶端上使用Websocket。。答案是: 不能
但是可以通過(guò)上面說(shuō)的 long poll 和 ajax 輪詢 來(lái) 模擬出類似的效果。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI