(轉!)大話websocket

邪正看眼鼻,真假看嘴脣,功名看氣概,富貴看精神。html

                                                                    ---曾國藩《冰鑑》web

轉自http://www.javashuo.com/article/p-uokgcivn-go.htmlajax

原文http://www.zhihu.com/question/20215561瀏覽器

1、websocket與http

WebSocket是HTML5出的東西(協議),也就是說HTTP協議沒有變化,或者說不要緊,但HTTP是不支持持久鏈接的(長鏈接,循環鏈接的不算)服務器

首先HTTP有 1.1 和 1.0 之說,也就是所謂的 keep-alive ,把多個HTTP請求合併爲一個,可是 Websocket 實際上是一個新協議,跟HTTP協議基本沒有關係,只是爲了兼容現有瀏覽器的握手規範而已,也就是說它是HTTP協議上的一種補充能夠經過這樣一張圖理解websocket

有交集,可是並非所有。併發

另外Html5是指的一系列新的API,或者說新規範,新技術。Http協議自己只有1.0和1.1,並且跟Html自己沒有直接關係。。通俗來講,你能夠用HTTP協議傳輸非Html數據,就是這樣=。=socket

再簡單來講,層級不同。ide

2、Websocket是什麼樣的協議,具體有什麼優勢

首先,Websocket是一個持久化的協議,相對於HTTP這種非持久的協議來講。簡單的舉個例子吧,用目前應用比較普遍的PHP生命週期來解釋。oop

HTTP的生命週期經過 Request 來界定,也就是一個 Request 一個 Response ,那麼在 HTTP1.0 中,此次HTTP請求就結束了。

在HTTP1.1中進行了改進,使得有一個keep-alive,也就是說,在一個HTTP鏈接中,能夠發送多個Request,接收多個Response。可是請記住 Request = Response, 在HTTP中永遠是這樣,也就是說一個request只能有一個response。並且這個response也是被動的,不能主動發起。

教練,你BB了這麼多,跟Websocket有什麼關係呢?_(:з」∠)_好吧,我正準備說Websocket呢。。

首先Websocket是基於HTTP協議的,或者說借用了HTTP的協議來完成一部分握手。

首先咱們來看個典型的 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的童鞋可能發現了,這段相似HTTP協議的握手請求中,多了幾個東西。我會順便講解下做用。

Upgrade: websocket Connection: Upgrade

這個就是Websocket的核心了,告訴 Apache 、 Nginx 等服務器:注意啦,我發起的是Websocket協議,快點幫我找到對應的助理處理~不是那個老土的HTTP。

Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw== Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13

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

而後, Sec_WebSocket-Protocol 是一個用戶定義的字符串,用來區分同URL下,不一樣的服務所須要的協議。簡單理解:今晚我要服務A,別搞錯啦~

最後, Sec-WebSocket-Version 是告訴服務器所使用的 Websocket Draft (協議版本),在最初的時候,Websocket協議還在 Draft 階段,各類奇奇怪怪的協議都有,並且還有不少期奇奇怪怪不一樣的東西,什麼Firefox和Chrome用的不是一個版本之類的,當初Websocket協議太多但是一個大難題。。不過如今還好,已經定下來啦~你們都使用的一個東西~ 脫水: 服務員,我要的是13歲的噢→_→

而後服務器會返回下列東西,表示已經接受到請求, 成功創建Websocket啦!

HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat

這裏開始就是HTTP最後負責的區域了,告訴客戶,我已經成功切換協議啦~

Upgrade: websocket Connection: Upgrade

依然是固定的,告訴客戶端即將升級的是 Websocket 協議,而不是mozillasocket,lurnarsocket或者shitsocket。

而後, Sec-WebSocket-Accept 這個則是通過服務器確認,而且加密事後的 Sec-WebSocket-Key 。 服務器:好啦好啦,知道啦,給你看個人ID CARD來證實行了吧。。

後面的, Sec-WebSocket-Protocol 則是表示最終使用的協議。

至此,HTTP已經完成它全部工做了,接下來就是徹底按照Websocket協議進行了。具體的協議就不在這闡述了。

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

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

好好好,年輕人,那咱們來說一講Websocket有什麼用。來給你吃點胡(蘇)蘿(丹)卜(紅)

3、Websocket的做用

在講Websocket以前,我就順帶着講下 long poll 和 ajax輪詢 的原理。

ajax輪詢

ajax輪詢的原理很是簡單,讓瀏覽器隔個幾秒就發送一次請求,詢問服務器是否有新信息。

場景再現:

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

服務端:沒有(Response)

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

服務端:沒有。。(Response)

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

服務端:你好煩啊,沒有啊。。(Response)

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

服務端:好啦好啦,有啦給你。(Response)

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

服務端:。。。。。沒。。。。沒。。。沒有(Response) —- loop

long poll

long poll 其實原理跟 ajax輪詢 差很少,都是採用輪詢的方式,不過採起的是阻塞模型(一直打電話,沒收到就不掛電話),也就是說,客戶端發起鏈接後,若是沒消息,就一直不返回Response給客戶端。直到有消息才返回,返回完以後,客戶端再次創建鏈接,周而復始。

場景再現:

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

服務端:額。。 等待到有消息的時候。。來 給你(Response)

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

從上面能夠看出其實這兩種方式,都是在不斷地創建HTTP鏈接,而後等待服務端處理,能夠體現HTTP協議的另一個特色,被動性。

何爲被動性呢,其實就是,服務端不能主動聯繫客戶端,只能有客戶端發起。

簡單地說就是,服務器是一個很懶的冰箱(這是個梗)(不會、不能主動發起鏈接),可是上司有命令,若是有客戶來,無論多麼累都要好好接待。

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

從上面很容易看出來,無論怎麼樣,上面這兩種都是很是消耗資源的。

ajax輪詢 須要服務器有很快的處理速度和資源。(速度)long poll 須要有很高的併發,也就是說同時接待客戶的能力。(場地大小)

因此 ajax輪詢 和 long poll 都有可能發生這種狀況。

客戶端:啦啦啦啦,有新信息麼?

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

客戶端:。。。。好吧,啦啦啦,有新信息麼?

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

客戶端:而後服務端在一旁忙的要死:冰箱,我要更多的冰箱!更多。。更多。。(我錯了。。這又是梗。。)

言歸正傳,咱們來講Websocket吧

經過上面這個例子,咱們能夠看出,這兩種方式都不是最好的方式,須要不少資源。

一種須要更快的速度,一種須要更多的’電話’。這兩種都會致使’電話’的需求愈來愈高。

哦對了,忘記說了HTTP仍是一個狀態協議。

通俗的說就是,服務器由於天天要接待太多客戶了,是個健忘鬼,你一掛電話,他就把你的東西全忘光了,把你的東西全丟掉了。你第二次還得再告訴服務器一遍。

因此在這種狀況下出現了,Websocket出現了。他解決了HTTP的這幾個難題。首先,被動性,當服務器完成協議升級後(HTTP->Websocket),服務端就能夠主動推送信息給客戶端啦。因此上面的情景能夠作以下修改。

客戶端:啦啦啦,我要創建Websocket協議,須要的服務:chat,Websocket協議版本:17(HTTP Request)

服務端:ok,確認,已升級爲Websocket協議(HTTP Protocols Switched)

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

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

服務端:balabalabalabala

服務端:balabalabalabala

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

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

就變成了這樣,只須要通過一次HTTP請求,就能夠作到源源不斷的信息傳送了。(在程序設計中,這種設計叫作回調,即:你有信息了再來通知我,而不是我傻乎乎的每次跑來問你 )

這樣的協議解決了上面同步有延遲,並且還很是消耗資源的這種狀況。那麼爲何他會解決服務器上消耗資源的問題呢?

其實咱們所用的程序是要通過兩層代理的,即HTTP協議在Nginx等服務器的解析下,而後再傳送給相應的Handler(PHP等)來處理。簡單地說,咱們有一個很是快速的 接線員(Nginx) ,他負責把問題轉交給相應的 客服(Handler) 。

自己接線員基本上速度是足夠的,可是每次都卡在客服(Handler)了,老有客服處理速度太慢。,致使客服不夠。Websocket就解決了這樣一個難題,創建後,能夠直接跟接線員創建持久鏈接,有信息的時候客服想辦法通知接線員,而後接線員在統一轉交給客戶。

這樣就能夠解決客服處理速度過慢的問題了。

同時,在傳統的方式上,要不斷的創建,關閉HTTP協議,因爲HTTP是非狀態性的,每次都要從新傳輸 identity info (鑑別信息),來告訴服務端你是誰。

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

可是Websocket只須要一次HTTP握手,因此說整個通信過程是創建在一次鏈接/狀態中,也就避免了HTTP的非狀態性,服務端會一直知道你的信息,直到你關閉請求,這樣就解決了接線員要反覆解析HTTP協議,還要查看identity info的信息。

同時由客戶主動詢問,轉換爲服務器(推送)有信息的時候就發送(固然客戶端仍是等主動發送信息過來的。。),沒有信息的時候就交給接線員(Nginx),不須要佔用自己速度就慢的客服(Handler)了

——————–

至於怎麼在不支持Websocket的客戶端上使用Websocket。。答案是: 不能

可是能夠經過上面說的 long poll 和 ajax 輪詢 來 模擬出相似的效果

相關文章
相關標籤/搜索