WebSocket 是什麼原理?為什麼可以實現持久連接?

WebSocket是HTML5出的東西 也就是說HTTP協議沒有變化 但HTTP是不支持持久連接的(長連接,循環連接的不算)

或者說WebSocket乾脆就不是基於HTTP來執行的。但是。。。說不通啊。。。

他是怎麼實現的呢??為什麼可以實現持久連接????

-----------------------------

【【【【【【【【【【【【【【補充】】】】】】】】】】:::::

既然WebSocket和HTTP是兩個協議 為什麼要在HTML5才支持

又如果說HTML5 出來以後可以用WebSocket了 就說明WebSocket是本來就有點東西只是HTML4不支持而已 http4時代 如何使用WebSocket呢?? 謝謝


額。。最高票答案沒答到點子上,最後怎麼跑到Nodejs上去了。。Websocket只是協議而已。。

我一個個來回答吧

一、WebSocket是HTML5出的東西(協議),也就是說HTTP協議沒有變化,或者說沒關係,但HTTP是不支持持久連接的(長連接,循環連接的不算)

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

有交集,但是並不是全部。

另外Html5是指的一系列新的API,或者說新規範,新技術。Http協議本身只有1.0和1.1,而且跟Html本身沒有直接關係。。

通俗來說,你可以用HTTP協議傳輸非Html數據,就是這樣=。=

再簡單來說,層級不一樣

二、Websocket是什麼樣的協議,具體有什麼優點

首先,Websocket是一個持久化的協議,相對於HTTP這種非持久的協議來說。

簡單的舉個例子吧,用目前應用比較廣泛的PHP生命周期來解釋。

1) 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的協議來完成一部分握手。

在握手階段是一樣的

-------以下涉及專業技術內容,不想看的可以跳過lol:,或者只看加黑內容--------

首先我們來看個典型的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有什麼用。

來給你吃點胡(蘇)蘿(丹)卜(紅)

三、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還是一個無狀態協議。(感謝評論區的各位指出OAQ)

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

所以在這種情況下出現了,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 輪詢來 模擬出類似的效果

-----

_(:з」∠)_兩天寫了兩篇科普類文章。。好累OAQ,求贊。。

對啦,如果有錯誤,歡迎大家在底下留言指出噢~


你可以把 WebSocket 看成是 HTTP 協議為了支持長連接所打的一個大補丁,它和 HTTP 有一些共性,是為了解決 HTTP 本身無法解決的某些問題而做出的一個改良設計。在以前 HTTP 協議中所謂的 keep-alive connection 是指在一次 TCP 連接中完成多個 HTTP 請求,但是對每個請求仍然要單獨發 header;所謂的 polling 是指從客戶端(一般就是瀏覽器)不斷主動的向伺服器發 HTTP 請求查詢是否有新數據。這兩種模式有一個共同的缺點,就是除了真正的數據部分外,伺服器和客戶端還要大量交換 HTTP header,信息交換效率很低。它們建立的「長連接」都是偽.長連接,只不過好處是不需要對現有的 HTTP server 和瀏覽器架構做修改就能實現。

WebSocket 解決的第一個問題是,通過第一個 HTTP request 建立了 TCP 連接之後,之後的交換數據都不需要再發 HTTP request了,使得這個長連接變成了一個真.長連接。但是不需要發送 HTTP header就能交換數據顯然和原有的 HTTP 協議是有區別的,所以它需要對伺服器和客戶端都進行升級才能實現。在此基礎上 WebSocket 還是一個雙通道的連接,在同一個 TCP 連接上既可以發也可以收信息。此外還有 multiplexing 功能,幾個不同的 URI 可以復用同一個 WebSocket 連接。這些都是原來的 HTTP 不能做到的。

另外說一點技術細節,因為看到有人提問 WebSocket 可能進入某種半死不活的狀態。這實際上也是原有網路世界的一些缺陷性設計。上面所說的 WebSocket 真.長連接雖然解決了伺服器和客戶端兩邊的問題,但坑爹的是網路應用除了伺服器和客戶端之外,另一個巨大的存在是中間的網路鏈路。一個 HTTP/WebSocket 連接往往要經過無數的路由,防火牆。你以為你的數據是在一個「連接」中發送的,實際上它要跨越千山萬水,經過無數次轉發,過濾,才能最終抵達終點。在這過程中,中間節點的處理方法很可能會讓你意想不到。

比如說,這些坑爹的中間節點可能會認為一份連接在一段時間內沒有數據發送就等於失效,它們會自作主張的切斷這些連接。在這種情況下,不論伺服器還是客戶端都不會收到任何提示,它們只會一廂情願的以為彼此間的紅線還在,徒勞地一邊又一邊地發送抵達不了彼岸的信息。而計算機網路協議棧的實現中又會有一層套一層的緩存,除非填滿這些緩存,你的程序根本不會發現任何錯誤。這樣,本來一個美好的 WebSocket 長連接,就可能在毫不知情的情況下進入了半死不活狀態。

而解決方案,WebSocket 的設計者們也早已想過。就是讓伺服器和客戶端能夠發送 Ping/Pong Frame(RFC 6455 - The WebSocket Protocol)。這種 Frame 是一種特殊的數據包,它只包含一些元數據而不需要真正的 Data Payload,可以在不影響 Application 的情況下維持住中間網路的連接狀態。


HTML5 是一個很寬廣的概念,是對大量新 API 的總稱。不存在 HTTP5 的概念,HTTP 最高的版本號是 1.1。簡單來說,你可以完全拋開 HTML5 和 HTML4 的概念,只考慮瀏覽器要麼支持 WebSocket,要麼不支持。

WebSocket 跟其他 API 比較不一樣的是,它不僅僅依賴於瀏覽器支持,同時要求伺服器和代理(假若需要經過代理的話)支持。WebSocket 本質上跟 HTTP 完全不一樣,只不過為了兼容性,WebSocket 的握手是以 HTTP 的形式發起的,如果伺服器或者代理不支持 WebSocket,它們會把這當做一個不認識的 HTTP 請求從而優雅地拒絕掉。

如果你真的很想知道這個協議具體是如何操作的,建議還是去看 RFC:http://tools.ietf.org/html/rfc6455


以下是騰訊雲技術社區整理的 WebSocket原理說明 ——

眾所周知,Web應用的通信過程通常是客戶端通過瀏覽器發出一個請求,伺服器端接收請求後進行處理並返回結果給客戶端,客戶端瀏覽器將信息呈現。這種機制對於信息變化不是特別頻繁的應用可以良好支撐,但對於實時要求高、海量並發的應用來說顯得捉襟見肘,尤其在當前業界移動互聯網蓬勃發展的趨勢下,高並發與用戶實時響應是Web應用經常面臨的問題,比如金融證券的實時信息、Web導航應用中的地理位置獲取、社交網路的實時消息推送等。

傳統的請求-響應模式的Web開發在處理此類業務場景時,通常採用實時通訊方案。比如常見的輪詢方案,其原理簡單易懂,就是客戶端以一定的時間間隔頻繁請求的方式向伺服器發送請求,來保持客戶端和伺服器端的數據同步。其問題也很明顯:當客戶端以固定頻率向伺服器端發送請求時,伺服器端的數據可能並沒有更新,帶來很多無謂請求,浪費帶寬,效率低下。

基於Flash,AdobeFlash通過自己的Socket實現完成數據交換,再利用Flash暴露出相應的介面給JavaScript調用,從而達到實時傳輸目的。此方式比輪詢要高效,且因為Flash安裝率高,應用場景廣泛。然而,移動互聯網終端上Flash的支持並不好:IOS系統中無法支持Flash,Android雖然支持Flash但實際的使用效果差強人意,且對移動設備的硬體配置要求較高。2012年Adobe官方宣布不再支持Android4.1+系統,宣告了Flash在移動終端上的死亡。

傳統的Web模式在處理高並發及實時性需求的時候,會遇到難以逾越的瓶頸,需要一種高效節能的雙向通信機制來保證數據的實時傳輸。在此背景下,基於HTML5規範的、有Web TCP之稱的 WebSocket應運而生。早期HTML5並沒有形成業界統一的規範,各個瀏覽器和應用伺服器廠商有著各異的類似實現,如IBM的MQTT、Comet開源框架等。直到2014年,HTML5終於塵埃落地,正式落實為實際標準規範,各個應用伺服器及瀏覽器廠商逐步開始統一,在 JavaEE7中也實現了WebSocket協議。至此無論是客戶端還是服務端的WebSocket都已完備。用戶可以查閱HTML5規範,熟悉新的HTML協議規範及WebSocket支持。

WebSocket 機制

以下簡要介紹一下WebSocket的原理及運行機制。

WebSocket是HTML5下一種新的協議。它實現了瀏覽器與伺服器全雙工通信,能更好的節省伺服器資源和帶寬並達到實時通訊的目的。它與HTTP一樣通過已建立的TCP連接來傳輸數據,但是它和HTTP最大不同是:

  • WebSocket是一種雙向通信協議。在建立連接後,WebSocket伺服器端和客戶端都能主動向對方發送或接收數據,就像Socket一樣;
  • WebSocket需要像TCP一樣,先建立連接,連接成功後才能相互通信。

傳統HTTP客戶端與伺服器請求響應模式如下圖所示:

WebSocket模式客戶端與伺服器請求響應模式如下圖:

上圖對比可以看出,相對於傳統HTTP每次請求-應答都需要客戶端與服務端建立連接的模式,WebSocket是類似Socket的TCP長連接通訊模式。一旦WebSocket連接建立後,後續數據都以幀序列的形式傳輸。在客戶端斷開WebSocket連接或Server端中斷連接前,不需要客戶端和服務端重新發起連接請求。在海量並發及客戶端與伺服器交互負載流量大的情況下,極大的節省了網路帶寬資源的消耗,有明顯的性能優勢,且客戶端發送和接受消息是在同一個持久連接上發起,實時性優勢明顯。

相比HTTP長連接,WebSocket有以下特點:

  • 是真正的全雙工方式,建立連接後客戶端與伺服器端是完全平等的,可以互相主動請求。而HTTP長連接基於HTTP,是傳統的客戶端對伺服器發起請求的模式。
  • HTTP長連接中,每次數據交換除了真正的數據部分外,伺服器和客戶端還要大量交換HTTP header,信息交換效率很低。Websocket協議通過第一個request建立了TCP連接之後,之後交換的數據都不需要發送 HTTP header就能交換數據,這顯然和原有的HTTP協議有區別所以它需要對伺服器和客戶端都進行升級才能實現(主流瀏覽器都已支持HTML5)。此外還有 multiplexing、不同的URL可以復用同一個WebSocket連接等功能。這些都是HTTP長連接不能做到的。

下面再通過客戶端和服務端交互的報文對比WebSocket通訊與傳統HTTP的不同點:

在客戶端,new WebSocket實例化一個新的WebSocket客戶端對象,請求類似 ws://yourdomain:port/path 的服務端WebSocket URL,客戶端WebSocket對象會自動解析並識別為WebSocket請求,並連接服務端埠,執行雙方握手過程,客戶端發送數據格式類似:

GET /webfin/websocket/ HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: xqBt3ImNzJbYqRINxEFlkg==
Origin: http://localhost:8080
Sec-WebSocket-Version: 13

可以看到,客戶端發起的WebSocket連接報文類似傳統HTTP報文,Upgrade:websocket參數值表明這是WebSocket類型請求,Sec-WebSocket-Key是WebSocket客戶端發送的一個 base64編碼的密文,要求服務端必須返回一個對應加密的Sec-WebSocket-Accept應答,否則客戶端會拋出Error during WebSocket handshake錯誤,並關閉連接。

服務端收到報文後返回的數據格式類似:

HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: K7DJLdLooIwIG/MOpvWFB3y3FE8=

Sec-WebSocket-Accept的值是服務端採用與客戶端一致的密鑰計算出來後返回客戶端的,HTTP/1.1 101 Switching Protocols表示服務端接受WebSocket協議的客戶端連接,經過這樣的請求-響應處理後,兩端的WebSocket連接握手成功, 後續就可以進行TCP通訊了。用戶可以查閱WebSocket協議棧了解WebSocket客戶端和服務端更詳細的交互數據格式。

在開發方面,WebSocket API 也十分簡單:只需要實例化 WebSocket,創建連接,然後服務端和客戶端就可以相互發送和響應消息。在WebSocket 實現及案例分析部分可以看到詳細的 WebSocket API 及代碼實現。

騰訊雲公網有日租類型七層負載均衡轉發部分支持Websocket,目前包括英魂之刃、銀漢遊戲等多家企業已接入使用。當出現不兼容問題時,請修改websocket配置,websocket server不校驗下圖中圈出的欄位:

一個使用WebSocket應用於視頻的業務思路如下:

  • 使用心跳維護websocket鏈路,探測客戶端端的網紅/主播是否在線
  • 設置負載均衡7層的proxy_read_timeout默認為60s
  • 設置心跳為50s,即可長期保持Websocket不斷開

近期Websocket將開放自定義配置,敬請期待。

相關閱讀推薦

WebSocket長連接應用場景

搭建多終端《你畫我猜》Socket伺服器


簡單說,沒錯,WebSocket不是HTTP協議,HTTP只負責建立WebSocket連接。


websocket約定了一個通信的規範,通過一個握手的機制,客戶端和伺服器之間能建立一個類似tcp的連接,從而方便它們之間的通信。在websocket出現之前,web交互一般是基於http協議的短連接或者長連接。websocket是一種全新的協議,不屬於http無狀態協議,協議名為"ws",這意味著一個websocket連接地址會是這樣的寫法:ws://**。websocket協議本質上是一個基於tcp的協議。分析HTML5中WebSocket的原理


是伺服器實現的。

客戶端通過html5與伺服器交互。http是不持續連接的,而websocket是。必須伺服器支持websocket協議,才有效。對於不支持websocket服務的伺服器,你客戶端怎麼寫代碼都沒用。

web伺服器必須支持websocket協議。我想這可以簡單的回答題主的問題。


題目的描述和很多回答里的概念都是錯的。

WebSocket 根本不是 HTML5 的東西。

WebSocket 是一個協議,歸屬於 IETF。

WebSocket API 是一個 Web API,歸屬於 W3C。

兩個規範是獨立發布的。

廣義上的 HTML5 裡面包含的是 WebSocket API,並不是 WebSocket。簡單的說,可以把 WebSocket 當成 HTTP,WebSocket API 當成 Ajax。

只是因為 WebSocket 對於非 Web 部分的意義不大(畢竟直接用 TCP 就好了),所以從現實角度的概率上而言 WebSocket 目前基本只會通過 Web API 里的 WebSocket API 來使用。

但並不等於 WebSocket 屬於 WebSocket API。


Web領域的實時推送技術,也被稱作Realtime技術。這種技術要達到的目的是讓用戶不需要刷新瀏覽器就可以獲得實時更新。它有著廣泛的應用場景,比如在線聊天室、在線客服系統、評論系統、WebIM等。

WebSocket簡介

談到Web實時推送,就不得不說WebSocket。在WebSocket出現之前,很多網站為了實現實時推送技術,通常採用的方案是輪詢(Polling)和Comet技術,Comet又可細分為兩種實現方式,一種是長輪詢機制,一種稱為流技術,這兩種方式實際上是對輪詢技術的改進,這些方案帶來很明顯的缺點,需要由瀏覽器對伺服器發出HTTP request,大量消耗伺服器帶寬和資源。面對這種狀況,HTML5定義了WebSocket協議,能更好的節省伺服器資源和帶寬並實現真正意義上的實時推送。

WebSocket協議本質上是一個基於TCP的協議,它由通信協議和編程API組成,WebSocket能夠在瀏覽器和伺服器之間建立雙向連接,以基於事件的方式,賦予瀏覽器實時通信能力。既然是雙向通信,就意味著伺服器端和客戶端可以同時發送並響應請求,而不再像HTTP的請求和響應。

為了建立一個WebSocket連接,客戶端瀏覽器首先要向伺服器發起一個HTTP請求,這個請求和通常的HTTP請求不同,包含了一些附加頭信息,其中附加頭信息」Upgrade: WebSocket」表明這是一個申請協議升級的HTTP請求,伺服器端解析這些附加的頭信息然後產生應答信息返回給客戶端,客戶端和伺服器端的WebSocket連接就建立起來了,雙方就可以通過這個連接通道自由的傳遞信息,並且這個連接會持續存在直到客戶端或者伺服器端的某一方主動的關閉連接。

一個典型WebSocket客戶端請求頭:

前面講到WebSocket是HTML5中新增的一種通信協議,這意味著一部分老版本瀏覽器(主要是IE10以下版本)並不具備這個功能, 通過百度統計的公開數據顯示,IE8目前仍以33%的市場份額佔據榜首,好在chrome瀏覽器市場份額逐年上升,現在以超過26%的市場份額位居第二,同時微軟前不久宣布停止對IE6的技術支持並提示用戶更新到新版本瀏覽器,這個曾經讓無數前端工程師為之頭疼的瀏覽器有望退出歷史舞台,再加上幾乎所有的智能手機瀏覽器都支持HTML5,所以使得WebSocket的實戰意義大增,但是無論如何,我們實際的項目中,仍然要考慮低版本瀏覽器的兼容方案:在支持WebSocket的瀏覽器中採用新技術,而在不支持WebSocket的瀏覽器里啟用Comet來接收發送消息。

WebSocket實戰

本文將以多人在線聊天應用作為實例場景,我們先來確定這個聊天應用的基本需求。

需求分析

1、兼容不支持WebSocket的低版本瀏覽器。

2、允許客戶端有相同的用戶名。

3、進入聊天室後可以看到當前在線的用戶和在線人數。

4、用戶上線或退出,所有在線的客戶端應該實時更新。

5、用戶發送消息,所有客戶端實時收取。

在實際的開發過程中,為了使用WebSocket介面構建Web應用,我們首先需要構建一個實現了 WebSocket規範的服務端,服務端的實現不受平台和開發語言的限制,只需要遵從WebSocket規範即可,目前已經出現了一些比較成熟的WebSocket服務端實現,比如本文使用的Node.js+http://Socket.IO。為什麼選用這個方案呢?先來簡單介紹下他們兩。

Node.js

Node.js採用C++語言編寫而成,它不是Javascript應用,而是一個Javascript的運行環境,據Node.js創始人Ryan Dahl回憶,他最初希望採用Ruby來寫Node.js,但是後來發現Ruby虛擬機的性能不能滿足他的要求,後來他嘗試採用V8引擎,所以選擇了C++語言。

Node.js支持的系統包括*nux、Windows,這意味著程序員可以編寫系統級或者伺服器端的Javascript代碼,交給Node.js來解釋執行。Node.js的Web開發框架Express,可以幫助程序員快速建立web站點,從2009年誕生至今,Node.js的成長的速度有目共睹,其發展前景獲得了技術社區的充分肯定。

http://Socket.IO

http://Socket.IO是一個開源的WebSocket庫,它通過Node.js實現WebSocket服務端,同時也提供客戶端JS庫。http://Socket.IO支持以事件為基礎的實時雙向通訊,它可以工作在任何平台、瀏覽器或移動設備。

http://Socket.IO支持4種協議:WebSocket、htmlfile、xhr-polling、jsonp-polling,它會自動根據瀏覽器選擇適合的通訊方式,從而讓開發者可以聚焦到功能的實現而不是平台的兼容性,同時http://Socket.IO具有不錯的穩定性和性能。

編碼實現

本文一開始的的插圖就是效果演示圖:可以點擊這裡查看在線演示,整個開發過程非常簡單,下面簡單記錄了開發步驟:

安裝Node.js

根據自己的操作系統,去Node.js官網下載安裝即可。如果成功安裝。在命令行輸入node -v和npm -v應該能看到相應的版本號。

搭建WebSocket服務端

這個環節我們儘可能的考慮真實生產環境,把WebSocket後端服務搭建成一個線上可以用域名訪問的服務,如果你是在本地開發環境,可以換成本地ip地址,或者使用一個虛擬域名指向本地ip。

先進入到你的工作目錄,比如 /workspace/wwwroot/plhwin/http://realtime.plhwin.com,新建一個名為package.json的文件,內容如下:

接下來使用npm命令安裝express和http://socket.io

安裝成功後,應該可以看到工作目錄下生成了一個名為node_modules的文件夾,裡面分別是express和http://socket.io,接下來可以開始編寫服務端的代碼了,新建一個文件:index.js

命令行運行node index.js,如果一切順利,你應該會看到返回的listening on *:3000字樣,這說明服務已經成功搭建了。此時瀏覽器中打開 http://localhost:3000 應該可以看到正常的歡迎頁面。

如果你想要讓服務運行在線上伺服器,並且可以通過域名訪問的話,可以使用Nginx做代理,在nginx.conf中添加如下配置,然後將域名(比如:http://realtime.plhwin.com)解析到伺服器IP即可。

完成以上步驟,http://realtime.plhwin.com:3000的後端服務就正常搭建了。

服務端代碼實現

前面講到的index.js運行在服務端,之前的代碼只是一個簡單的WebServer歡迎內容,讓我們把WebSocket服務端完整的實現代碼加入進去,整個服務端就可以處理客戶端的請求了。完整的index.js代碼如下:

客戶端代碼實現

進入客戶端工作目錄/workspace/wwwroot/plhwin/http://demo.plhwin.com/chat,新建一個index.html:

上面的html內容本身沒有什麼好說的,我們主要看看裡面的4個文件請求:

1、http://realtime.plhwin.com:3000/socket.io/socket.io.js

2、style.css

3、json3.min.js

4、client.js

第1個JS是http://Socket.IO提供的客戶端JS文件,在前面安裝服務端的步驟中,當npm安裝完http://socket.io並搭建起WebServer後,這個JS文件就可以正常訪問了。

第2個style.css文件沒什麼好說的,就是樣式文件而已。

第3個JS只在IE8以下版本的IE瀏覽器中載入,目的是讓這些低版本的IE瀏覽器也能處理json,這是一個開源的JS,詳見:JSON 3

第4個client.js是完整的客戶端的業務邏輯實現代碼,它的內容如下:

至此所有的編碼開發工作全部完成了,在瀏覽器中打開 http://demo.plhwin.com/chat/ 就可以看到效果了。

上面所有的客戶端和服務端的代碼可以從Github上獲得,地址:https://github.com/plhwin/nodejs-socketio-chat

下載本地後有兩個文件夾 client 和 server,client文件夾是客戶端源碼,可以放在Nginx/Apache的WebServer中,也可以放在Node.js的WebServer中。後面的server文件夾里的代碼是websocket服務端代碼,放在Node.js環境中,使用npm安裝完 express 和 http://socket.io 後,node index.js 啟動後端服務就可以了。

留給我們的思考

1、假設是一個在線客服系統,裡面有許多的公司使用你的服務,每個公司自己的用戶可以通過一個專屬URL地址進入該公司的聊天室,聊天是一對一的,每個公司可以新建多個客服人員,每個客服人員可以同時和客戶端的多個用戶聊天。

2、又假設是一個在線WebIM系統,實現類似微信,qq的功能,客戶端可以看到好友在線狀態,在線列表,添加好友,刪除好友,新建群組等,消息的發送除了支持基本的文字外,還能支持表情、圖片和文件。

有興趣的同學可以繼續深入研究。

--------------------------

上面是我前段時間寫的一篇與WebSocket這個主題相關的文檔,就直接貼過來了,原文請見:使用Node.js+Socket.IO搭建WebSocket實時應用


先說結論:「websocket出現是因為瀏覽器不給開後門」,「不是WebSocket基於HTTP,相反,可以看成可以看成可以看成HTTP基於WebSocket」。

要理解為什麼會出現HTTP,WebSocket,可以做這樣一個假設。

假設平行宇宙1984年(我懶的查數據,所以就說一個平行宇宙了,隨便看看吧),人們使用TCP協議進行通訊,假設那時候還沒有網頁瀏覽器這一說法,大家都是通過各種軟體直接通訊。

假設到了1986年,人們使用瀏覽器來瀏覽網頁,假設當時電腦時100MHz,100M內存。對TCP協議熟悉一點,大概也能猜到一個TCP鏈接,會消耗一點點內存,假設是32k(具體我也不知道),那麼如果一台幾萬塊錢的伺服器最大能支持100M/32k=3200個連接。顯然,如果一個公司,面向全世界提供網頁服務,如果使用TCP,最多也就3200個人同時看網頁。

於是伺服器要求「所有客戶端,打開網頁之後,必須關閉TCP連接」。這就是(猜測的)HTTP的初衷了。

按照這個協議,伺服器接受TCP連接,幾秒鐘之內讀取數據,檢驗之後,回複數據,斷開連接。所謂的節省「資源」也沒說明白到底節省了什麼「資源」。

等到二十年後,平行宇宙的2004年,QQ桌面版好好的,QQ網頁版用的越來越多。由於瀏覽器都是連接之後很快斷開,QQ網頁版,只能靠各種polling方式持續交互數據(HTTP keep-alive也有自己的缺點,其他答主講的很好),浪費大量的帶寬(這時候帶寬的費用就大了),同時客戶端收到消息也不及時,還有各種其它問題。

QQ網頁版想直接用TCP協議長時間連接,但是QQ網頁版能做的,都是瀏覽器允許做的。可以說,websocket的出現,就是因為瀏覽器不支持TCP直連,不給開後門。

於是「希望所有的瀏覽器都能夠直接進行TCP連接」,於是瀏覽器出現了websocket協議。

所以,因為某些原因,人們在TCP上面弄了一個HTTP協議,把TCP支持的一些特性刪除了,然後若干年之後想要那些被刪除的特性,返回TCP,於是出現了WebSocket。

WebSocket實際上可以看作HTTP的降級!「不是WebSocket基於HTTP,而是可以看成可以看成可以看成HTTP基於WebSocket」。

具體協議細節其他答主講的很好,就不重複了。包括從串口模擬出TCP,再模擬出HTTP,流介面變成塊介面,都無所謂了。


websocket的實現已經有朋友提到了基於HTTP來發起,我這裡不討論太多實現,而是主要回答一下題主補充的問題:「【【【【【【【【【【【【【【補充】】】】】】】】】】:::::

既然WebSocket和HTTP是兩個協議 為什麼要在HTML5才支持

又如果說HTML5 出來以後可以用WebSocket了 就說明WebSocket是本來就有點東西只是HTML4不支持而已 http4時代 如何使用WebSocket呢?? 謝謝」

websocket是隨著WWW的發展,應用場景越來越複雜而提出的,針對瀏覽器和web伺服器之間雙向持續通信而設計,而且優雅地兼容HTTP(我猜想:同時因為建立在HTTP上,也可以利用好HTTP原有的基礎比如basic認證)。它和HTML5不是非得扯到一起,但是剛好是同時期,而且HTML5也剛好需要「socket」功能,因此順理成章成為一部分。

而 websocket 的使用,更多的是「腳本」層面的事情,比如在javascript(不是非得javascript,但是javascript已經成為和瀏覽器交互的事實標準)中創建Websocket對象以便操作瀏覽器的websocket功能(這個功能便是瀏覽器根據HTML5草案實現出來的,參考草案的interface WebSocket部分定義),然後註冊onopen/onmessage等回調介面,有數據或者狀態變更之類的時機你就可以做相應的處理了。而這部分剛好在舊的標準沒定義,瀏覽器也沒有這樣的功能,因此遵循HTML4編寫的頁面不會用到這些功能。


前言

針對以上您提起的WebSocket的相關話題,給您做一下系統的梳理,WebSocket是和http類似的可以實現全雙工可持久連接通信的應用層協議,以下深入剖析一下WebSocket的原理。

什麼是WebSocket

首先,我們需要弄明白,WebSocket本質上一種計算機網路應用層的協議,用來彌補http協議在持久通信能力上的不足。

我們知道http協議本身是無狀態協議,每一個新的http請求,只能通過客戶端主動發起,通過 建立連接--&>傳輸數據--&>斷開連接 的方式來傳輸數據,傳送完連接就斷開了,也就是這次http請求已經完全結束了(雖然http1.1增加了keep-alive請求頭可以通過一條通道請求多次,但本質上還是一樣的)。

並且伺服器是不能主動給客戶端發送數據的(因為之前的請求得到響應後連接就斷開了,之後伺服器根本不知道誰請求過),客戶端也不會知道之前請求的任何信息。

所以說,http協議本身是沒有持久通信能力的,但是我們在實際的應用中,是很需要這種能力的,所以WebSocket協議由此而生,於2011年被IETF定為標準RFC6455,並被RFC7936所補充規範。

並且在HTML5標準中增加了有關WebSocket協議的相關api,所以只要實現了HTML5標準的客戶端,就可以與支持WebSocket協議的伺服器進行全雙工的持久通信了。

ps:這裡的持久通信能力指的是協議本身的能力,我們當然可以通過編程的方式實現這種功能,比如輪詢的方式,但誰不喜歡原生就支持呢?

ps2:計算機網路里還有socket關鍵字,這裡的socket指的是運輸層協議的某一端,泛指某個應用程序。

ps3: unix編程里還有一個socket介面,這裡的譯名是套接字,泛指應用層協議的埠號。

WebSocket協議的原理

與http協議一樣,WebSocket協議也需要通過已建立的TCP連接來傳輸數據。具體實現上是通過http協議建立通道,然後在此基礎上用真正的WebSocket協議進行通信,所以WebSocket協議和http協議是有一定的交叉關係的。

下面是WebSocket協議請求頭:

其中請求頭中重要的欄位:

Connection:Upgrade

Upgrade:websocket

Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits

Sec-WebSocket-Key:mg8LvEqrB2vLpyCNnCJV3Q==

Sec-WebSocket-Version:13

1. Connection和Upgrade欄位告訴伺服器,客戶端發起的是WebSocket協議請求

2. Sec-WebSocket-Extensions表示客戶端想要表達的協議級的擴展

3. Sec-WebSocket-Key是一個Base64編碼值,由瀏覽器隨機生成

4. Sec-WebSocket-Version表明客戶端所使用的協議版本

而得到的響應頭中重要的欄位:

Connection:Upgrade

Upgrade:websocket

Sec-WebSocket-Accept:AYtwtwampsFjE0lu3kFQrmOCzLQ=

1. Connection和Upgrade欄位與請求頭中的作用相同

2. Sec-WebSocket-Accept表明伺服器接受了客戶端的請求

Status Code:101 Switching Protocols

並且http請求完成後響應的狀態碼為101,表示切換了協議,說明WebSocket協議通過http協議來建立運輸層的TCP連接,之後便與http協議無關了。

WebSocket協議具體內容請參考:https://github.com/zhangkaitao/websocket-protocol

WebSocket協議的優缺點

優點:

· WebSocket協議一旦建議後,互相溝通所消耗的請求頭是很小的

· 伺服器可以向客戶端推送消息了

缺點:

· 少部分瀏覽器不支持,瀏覽器支持的程度與方式有區別

WebSocket協議的應用場景

· 即時聊天通信

· 多玩家遊戲

· 在線協同編輯/編輯

· 實時數據流的拉取與推送

· 體育/遊戲實況

· 實時地圖位置

NodeJS的簡單實現

服務端

// 安裝ws模塊// npm install ws// 新建index.js文件// -----
// 導入ws模塊const WebSocket = require("ws")
// 新建一個WebSocketServerconst wss = new WebSocket.Server({ port: 3000 })
// 伺服器監聽連接事件
wss.on("connection", ws =&> {

// 伺服器監聽消息事件
ws.on("message", msg =&> {
console.log("伺服器收到:", msg)
})

// 伺服器向客戶端發送消息
ws.send("這是伺服器發送的信息")
})

客戶端

&&&
&
&
&
&Document&&
&&
// 這是瀏覽器原生支持的WebSocket API,在支持HTML5標準的瀏覽器上可以直接使用
var ws = new WebSocket("ws://localhost:3000")

// 當連接成功後就可以發送消息了
ws.onopen = function() {
console.log("連接已建立")
ws.send("這是客戶端發出的信息")
}
// 收到消息後做對應的處理
ws.onmessage = function(e) {
console.log(e.data)
}&&&

運行結果

伺服器端

瀏覽器端

希望能幫到你。


本人親身經驗告訴你!!!

HTTP是運行在TCP協議傳輸層上的應用協議,而WebSocket是通過HTTP協議協商如何連接,然後獨立運行在TCP協議傳輸層上的應用協議。你需要知道WebSocket僅僅是利用了HTTP協議做連接請求。WebSocket相當於一個簡化版的TCP傳輸子層(實際上WebSocket也是應用層協議)。WebSocket之所以能持久連接原因是它運行在TCP協議上,TCP協議自身是長連接協議,所以WebSocket當然可以長連接啦。

如果你要問為什麼HTTP不是長連接,原因是早期的HTTP在發起每個請求,響應完成後就會關閉Socket。但是後來加了多路復用KeepAlive協議後HTTP協議已經可以實現長連接了,可以處理長連接事務了。

至於添加WebSocket特性,是為了更好、更靈活,輕量的與伺服器通訊。因為WebSocket提供了簡單的消息規範,可以更快的適應長連接的環境,其實現在HTTP協議自身就可以做,但是不太輕便。

為什麼HTML4不支持WebSocket?原因是WebSocket的協商機制HTML4底層API沒有實現。

就不要陷入誤區啦!!!

推薦你先看看網路的7層協議,分清楚每一層做什麼事在說!


作者:雪域初塵

鏈接:WebSocket全雙工通信入門教程 - 雪域初塵的文章 - 知乎專欄

來源:知乎

著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。

1. 什麼是WebSocket

WebSocket protocol 是HTML5一種新的協議。它實現了瀏覽器與伺服器全雙工通信(full-duplex)。一開始的握手需要藉助HTTP請求完成。

1. 傳統的web通信方式

1. 工作模式:客戶端請求-服務端響應

2. 適用場景:信息變化不是特別頻繁的場合,如網頁刷新

3. 不適用場景:在線遊戲,實時監控

4. 問題

佔用網路傳輸帶寬:每次請求和應答都帶有完整的Http頭,這就增加了每次傳輸的數據量。

實時性差:在全雙工通信時常採用輪詢進行。

2. 改進版web通信方式

1. 輪詢

1. 基於polling(輪詢)技術:以頻繁請求方式來保持客戶端和服務端的同步

2. 問題:客戶端的頻繁的請求,服務端的數據無變化,造成通信低效

2. 長輪詢

1. 當服務端沒有數據更新的時候,連接會保持一段時間周期知道數據或者狀態改變或者過期,依次減少無效的客戶端和服務端的交互

2. 當服務端數據變更頻繁的話,這種機制和定時輪詢毫無區別

3. 流技術

1. 在客戶端頁面通過一個隱藏的窗口向服務端發出一個長連接請求。服務端接到這個請求後作出回應並不斷更新鏈接狀態以保證客戶端和服務端的連接不過期。

2. 瀏覽器設計兼容和並發處理問題。

4. websocket

1. 概念:是html5開始提供的一種在單個TCP連接上進行全雙工通訊協議。Websocket通信協議與2011年倍IETF定為標準RFC 6455,Websocket API被W3C定為標準。

2. 原理和TCP一樣,只需做一個握手動作,就可以形成一條快速通道。

1. 客戶端發起http請求,附加頭信息為:「Upgrade Websocket」

2. 服務端解析,並返回握手信息,從而建立連接

3. 傳輸數據(雙向)

4. 斷開連接

3. 數據傳輸過程

1. 以幀形式進行傳輸

1. 大數據分片

2. 支持邊生成數據,把你傳遞消息

2. 說明

1. 客戶端到服務端的數據幀必須進行掩碼處理,服務端拖接收到未經掩碼處理的數據幀,須主動關閉連接

2. 服務端到客戶端的數據一定不能加掩碼,客戶端接收到經過掩碼的實際幀,須主動關閉連接

3. 發現錯誤的一方可以發送close幀,關閉連接。

4. 優勢

1. 數據傳輸量

2. 穩定性

5. 支持瀏覽器

1. Firefox 4、Chrome 4、Opera 10.70以及Safari 5等瀏覽器的支持

2. websocket案例說明

1. 客戶端

1. 創建Websocket實例

ws = new WebSocket("ws://127.0.0.1:10000/Server_Test.php");

1. 伺服器IP:ws://127.0.0.1

2. 伺服器埠:10000

3. 服務程序:Server_Test.php

2. 建立連接後回調函數

ws.onopen = function(event){}

3. 收到服務端消息後回調函數

ws.onmessage = function(event){}

4. 關閉連接後回調函數

ws.onclose = function(event){}

5. 連接錯誤後回調函數

ws.onerror = function(event)

6. 發送數據

ws.send("伺服器,您好");

7. 查看當前連接狀態

alert(ws.readyState)

2. 服務端

1. 創建服務端WebSocket對象,等待客戶端接入

$master = WebSocket("localhost",10000);

首先創建Websocket,然後服務端監聽相應埠,等待客戶端接入

function WebSocket($address,$port){

$master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() failed");

socket_set_option($master, SOL_SOCKET, SO_REUSEADDR, 1) or die("socket_option() failed");

socket_bind($master, $address, $port) or die("socket_bind() failed");

socket_listen($master,20) or die("socket_listen() failed");

echo "Server Started : ".date("Y-m-d H:i:s")."
";

echo "Master socket : ".$master."
";

echo "Listening on : ".$address." port ".$port."

";

return $master;

}

2. 從WebSocket中讀取數據

$buffer = socket_read($socket,2048);

3. 當收到客戶端首次連接請求後,生成握手信息並回復

$return_str = dohandshake($buffer);

socket_write($socket,$return_str,strlen($return_str));

4. 連接後,即可接收並解析出客戶端的數據

$buffer = socket_read($socket,2048);

$data_str = decode($buffer);

5. 接收到用戶數據後,直接回復客戶端

socket_write($socket,$return_str,strlen($return_str));

6. 斷開連接

socket_close($socket);

7. 以上6步完成全雙工通信

3. 本案例說明

1. 目前只可傳文本,byte傳輸還需進一步研究

3. 案例運行流程

首先需要安裝PHP study,然後將服務端代碼放到PHP study可執行目錄下,最後使用瀏覽器打開客戶端代碼去訪問伺服器即可進行通信。

1. 安裝PHP study,然後將PHP文件放到 D:phpStudyWWW

2. 設置PHP study埠:

3. 在客戶端程序中通過url去訪問伺服器:

4. 調試說明

1. 客戶端代碼

1. html代碼使用Hbuilder編輯完成

2. 列印信息使用

console.log("已經與伺服器建立了連接rn當前連接狀態:" + this.readyState);

3. 列印信息可以實時輸出到控制台

2. 服務端代碼

1. 服務端代碼編輯同樣在Hbuilder中完成

2. 服務端代碼調試工具推薦使用Xdebug,我們目前使用的是列印錯誤日誌方式進行調試

error_log("客戶端發送數據: $data_str
", 3, "D:/phpStudy/WWW/error.log");

3. 注意,D:/phpStudy/WWW/error.log為日誌輸出路徑

5. 源碼下載

請到 定為電子俱樂部 下載


我師妹給 @Ovear 配的圖...

伺服器和客戶端的日常


大家回答的都不錯,但要解答題主的困惑,還是讓我換角度來解答吧。

Websocket顧名思義是web範疇里的socket,那麼web 範疇外的socket 題主可能沒接觸過,所以對長連接表示不可思議。比如題主可以先搜索下"Java tcp socket編程"來理解下socket,socket協議本身是跨平台的,不同的系統封裝上會有差別。(這裡不提tcp udp的區別)

所以通過socket 和伺服器保持長鏈接是平常的事情。

但web開發中卻沒有能保持長連接的協議 ,那麼html5隻是解決了從沒有到有,websocket就誕生了。websocket為滿足web 的開發方式,或者說web 通訊方式,或者說web的表達方式,它兼容部分http協議,比如建立連接,讓web開發很容易的通過http 方式建立websocket連接 ,總之websocket 設計還是很巧妙的。

歸根結底,從開發角度講它的底層還是tcp socket編程,從協議角度講它走的還是tcp/ip協議,世界並沒有為websocket 創建新的傳輸層協議,它並沒有多麼神奇。


"或者說WebSocket乾脆就不是基於HTTP來執行的",這句是對的,WebSocket 和 HTTP 都是基於 TCP 的,TCP是傳輸層協議, WebSocket 和 HTTP是應用層協議,就是因為HTTP不能滿足特定的需求才被設計出來的,所以會支持你說的那些特性。


高票答案的敘事能力堪憂。文章過於賣萌而降低了對真正有用的信息的信噪比。

網路連接的本質上就是通信,那麼通信不管你是用嘴喊還是用揮手還是網路上發一個光電信號其實原理都是一樣的。

電腦的介面不停的接受信號,和你的耳朵不停的接受聲音有什麼區別?

想像一下,如果這個世界上沒有網路,只有書信的方式通信,你的ip和伺服器的ip的區別 只有 一個是不知名一個是知名的區別,一個好找一個不好找的區別。你是動態ip,你可以把你自己想像成一個經常在宿舍 教學樓 酒吧到處亂跑的毛孩子,而給你分配動態ip的路由 就相當於是那些指揮你去上課 指揮你去睡覺的人,他們知道你在哪。而伺服器買的靜態ip,只是他們的ip被更多的人(dns)等知道在那,能更快的找到的區別。

要與伺服器通信。好比,你要找奧巴馬發一封信,很好找,而奧巴馬回信卻不知道你在什麼旮旯里,他回信不需要記憶你的地址只需要送信的 告訴原路返回即可,這就是http,它是無狀態的無記憶的。websocket tcp連接就是奧巴馬已經記住你的地址了,這樣他可以直接向你發信。 奧巴馬擔心你收不到信,比如如果你已經掛了,或者送信的掛了 他還會每秒鐘都發一個信號給你,確認你是不是能夠收到信,如果真的收不到了 就不在給你發了,那就是心跳。


總結下:tcp是通信層協議,全雙工同行,(連接後,A,B兩端同時交流)

再TCP協議基礎上的兩個應用層協議,http,webscoket協議,

webscoket協議是全雙工通信,不過需要用類似於http的方式和後台建立鏈接,然後通信。


HTTP和WebSocket都是應用層協議,傳輸層協議是TCP,應用層解決如何包裝數據問題,HTTP和WebSocket兩者的差距不大。

瀏覽網頁時,經過三個過程

1、瀏覽器經過三次握手與web伺服器建立鏈接,

2、web伺服器返迴響應

3、瀏覽器通過四次握手主動斷開鏈接

因為第三步導致不能持久鏈接,那我們去掉第三步不就可以了實現持久鏈接了嗎?這就是WebSocket與HTTP最大的不同(Web伺服器是不會主動斷開連接的),當然還有更多的數據封裝格式的不同。

可以看到WebSocket是在HTTP上做的改動,我曾經用單片機的TCP/IP協議棧封裝符合HTTP協議格式的字元串,去連接Web伺服器。WebSocket和HTML5沒有多大關係。


推薦閱讀:

關於ajax請求的安全,如何避免csrf類似的攻擊?
Aspera技術如何實現原來需要傳26小時的24GB文檔做到只需30秒?
為什麼fiddler無法抓到訊飛語音輸入的請求?
怎麼瀏覽器打開圖片的url默認是下載?

TAG:HTML5 | HTTP | WebSocket |