WebSocket詳解(六):刨根問底WebSocket與Socket的關係

jsjsjjs發表於2017-12-15

1、前言

對於很多初次接觸Web端即時通訊技術的人來說,WebSocket是個很新的概念,但無疑它是當前Web端即時通訊技術中最熱門的關鍵詞。隨便點開一篇文章,只要說打算開發Web端即時通訊相關的的應用,老司機們推薦的無一例外都是WebSocket。

那麼好了,我知道應該用WebSocket,但本著知其然知其所以然的碼農習慣,我還是需要了解下面這些問題:

1)Socket 和 WebSocket 有哪些區別和聯絡?

2)WebSocket 和 HTML5 是什麼關係?

3)必須在瀏覽器中才能使用 WebSocket 嗎?

4)WebSocket 能和 Socket 一樣傳輸 raw 資料麼?

5)WebSocket 和 Socket 相比會多耗費流量麼?

但是,目前網上全面介紹這兩種協議的中文文章並不多,或者說不夠全面。我無法找到一篇文章能解決上面的所有問題。因此,我寫了本文,把找到的 Socket 和 WebSocket 的相關資料做一個梳理,以方便理解。

本文並不能直接完整回答上面提出的幾個問題,但讀完本文,要理解上面的那些問題,是很容易的事。由於能力有限,本文不可能很長。而且,技術細節並非所有人都願意仔細瞭解。但本文包含了大量的外部連結,跟隨這些連結,可以找到足夠多的細節,滿足你/我的求知慾。Are you ready?

學習交流:

– 即時通訊開發交流群:320837163[推薦]

– 移動端IM開發入門文章:《新手入門一篇就夠:從零開發移動端IM

(本文同步釋出於:http://www.52im.net/thread-1273-1-1.html

2、系列文章

本文是系列文章中的第5篇,本系列文章的大綱如下:

WebSocket詳解(一):初步認識WebSocket技術

WebSocket詳解(二):技術原理、程式碼演示和應用案例

WebSocket詳解(三):深入WebSocket通訊協議細節

WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)

WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)

WebSocket詳解(六):刨根問底WebSocket與Socket的關係》(本文)

《WebSocket詳解(七):WebSocket協議與Socket.io開源工程》

3、更多資料

Web端即時通訊新手入門貼:

新手入門貼:詳解Web端即時通訊技術的原理

Web端即時通訊技術盤點請參見:

Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE

關於Ajax短輪詢:

找這方面的資料沒什麼意義,除非忽悠客戶,否則請考慮其它3種方案即可。

有關Comet技術�的詳細介紹請參見:

Comet技術詳解:基於HTTP長連線的Web端實時通訊技術

WEB端即時通訊:HTTP長連線、長輪詢(long polling)詳解

WEB端即時通訊:不用WebSocket也一樣能搞定訊息的即時性

開源Comet伺服器iComet:支援百萬併發的Web端即時通訊�方案

有關WebSocket的詳細介紹請參見:

新手快速入門:WebSocket簡明教程

WebSocket詳解(一):初步認識WebSocket技術

WebSocket詳解(二):技術原理、程式碼演示和應用案例

WebSocket詳解(三):深入WebSocket通訊協議細節

Socket.IO介紹:支援WebSocket、用於WEB端的即時通訊的框架

socket.io和websocket 之間是什麼關係?有什麼區別?

有關SSE的詳細介紹文章請參見:

SSE技術詳解:一種全新的HTML5伺服器推送事件技術

更多WEB端即時通訊文章請見:

http://www.52im.net/forum.php?mod=collection&action=view&ctid=15

4、技術對比

選擇了 WebSocket 技術之後,不可避免的,我要將它和其他協議以及技術做一下比較。最常見的,就是需要比較 WebSocket 與 HTTP、Socket 技術的異同。本系列文章中《WebSocket詳解(四):刨根問底HTTP與WebSocket的關係(上篇)》、《WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)》兩篇詳細討論了WebSocket和HTTP的關係,那麼本篇將只討論WebSocket和Socket的話題。

WebSocket 是為了滿足基於 Web 的日益增長的實時通訊需求而產生的。在傳統的 Web 中,要實現實時通訊(比如網頁的QQ,聊天系統等),通用的方式是採用 HTTP 協議不斷髮送請求(按照以往的技術能力通常是採用輪詢、Comet技術解決)。

HTTP協議是非持久化的,單向的網路協議,在建立連線後只允許瀏覽器向伺服器發出請求後,伺服器才能返回相應的資料。當需要即時通訊時,通過輪詢在特定的時間間隔(如1秒),由瀏覽器向伺服器傳送Request請求,然後將最新的資料返回給瀏覽器。這樣的方法最明顯的缺點就是需要不斷的傳送請求,而且通常HTTP request的Header是非常長的,為了傳輸一個很小的資料 需要付出巨大的代價,是很不合算的,佔用了很多的寬頻。這種方式即浪費頻寬(HTTP HEAD 是比較大的),又消耗伺服器 CPU 佔用(沒有資訊也要接受請求)。

▲ 輪詢和WebSocket技術在網路延遲上的對比(本圖來自:websocket.org)

而是用 WebSocket 技術,則會大幅降低上面提到的消耗,如下圖所示。

▲ 輪詢和WebSocket技術在資料流量消耗上的對比(本圖來自:websocket.org)

關於更詳細的描述,尹立的這篇文章講得非常好:《WebSocket(2)–為什麼引入WebSocket協議》。

那麼,WebSocket 到底和 Socket 又有什麼聯絡?這就要講到 OSI 模型和 TCP/IP 協議族。

5、OSI 模型與 TCP/IP

以下是維基百科中關於OSI 模型的說明:

開放式系統互聯通訊參考模型(英語:Open System Interconnection Reference Model,ISO/IEC 7498-1),簡稱為OSI模型(OSI model),一種概念模型,由國際標準化組織(ISO)提出,一個試圖使各種計算機在世界範圍內互連為網路的標準框架。

而 TCP/IP 協議可以看做是對 OSI 模型的一種簡化(以下內容來自維基百科):

它將軟體通訊過程抽象化為四個抽象層,採取協議堆疊的方式,分別實作出不同通訊協議。協議套組下的各種協議,依其功能不同,被分別歸屬到這四個階層之中7,常被視為是簡化的七層OSI模型。

這裡有一張圖詳細介紹了 TCP/IP 協議族中的各個協議在 OSI模型 中的分佈,一圖勝千言(此圖高清版:點此下載):

TCP/IP 協議和 OSI 模型的內容,在網際網路上有很多。我沒有必要再次介紹它們。在這裡,我們只需要知道,HTTP、WebSocket 等協議都是處於 OSI 模型的最高層: 應用層 。而 IP 協議工作在網路層(第3層),TCP 協議工作在傳輸層(第4層)。

至於 OSI 模型的各個層次都有什麼系統和它們對應,這裡有篇很好的文章可以滿足大家的求知慾:OSI七層模型詳解

6、WebSocket 與 TCP

從上面的圖中可以看出,HTTP、WebSocket 等應用層協議,都是基於 TCP 協議來傳輸資料的,我們可以把這些高階協議理解成對 TCP 的封裝。

既然大家都使用 TCP 協議,那麼大家的連線和斷開,都要遵循TCP 協議中的三次握手和四次握手,只是在連線之後傳送的內容不同,或者是斷開的時間不同。

更詳細內容可閱讀:wireshark抓包圖解 TCP三次握手/四次揮手詳解》。

對於 WebSocket 來說,它必須依賴 HTTP 協議進行一次握手 ,握手成功後,資料就直接從 TCP 通道傳輸,與 HTTP 無關了(具體可見文章《WebSocket詳解(五):刨根問底HTTP與WebSocket的關係(下篇)》)。

7、再來八卦一下WebSocket的由來

由於年代久遠,計算機方面很多事情也搞不了那麼清楚。但WebSocket是一個很新的東西,可以讓我們看到它是如何成為現在我們看到的這個樣子的。

7.1 WHATWG(Web Hypertext Application Technology Working Group)

關於HTML5的故事很多人都是知道的,w3c放棄了HTML,然後有一群人(也有說是這些人供職的公司,不過官方的文件上是說的個人)創立了WHATWG組織來推動HTML語言的繼續發展,同時,他們還發展了很多關於Web的技術標準,這些標準不斷地被官方所接受。WebSocket就屬於WHATWG釋出的Web Application的一部分(即HTML5)的產物。

7.2 為什麼會有WebSocket

大約在08年的時候,WG的工程師在討論網路環境中需要一種全雙工的連線形式,剛開始一直叫做「TCPConnection」,並討論了這種協議需要支援的功能,大致已經和我們今天看到的WebSocket差不多了。他們認為基於現有的HTTP之上的一些技術(如長輪詢、Comet)並滿足不了這種需求,有必要定義一個全新的協議。

7.3 名稱的由來

在很多的關於HTML5或者WebSocket的文件中,都能看到一個名字,Hixie(Ian Hickson),他是WHATWG組織的發言人,曾供職於Netscape、Opera、Google,看工作的公司就知道這個人的背景了。

▲ hixie

08年6月18日,一群WHATWG的工程師在討論一些技術問題,一個工程師提到說「我們之前討論的那個東西,不要叫TCPConnection 了,還是起個別的名字吧 」,接著幾個名字被提及,DuplexConnection,TCPSocket,SocketConnection ,一個叫mcarter(Michael Carter )的工程師說他馬上要寫一篇關於Comet的文章,如果可以確定這個名稱,想在文章中引用這個名字。

Socket一直以來都被人用來表示網路中一個連線的兩端,考慮到怎麼讓工程師更容易接受,後來Hixie說了一句「我看WebSocket這個名字就很適合嘛(Hixie briefly pops back online to record that “WebSocket” would probably be a good new name for the TCPConnection object)」,大家都沒有異議,緊接著mcarter在Comet Daily中發表了文章《Independence Day: HTML5 WebSocket Liberates Comet From Hacks》,後來隨著各大瀏覽器對WebSocket的支援,它變成了實際的標準,IETF也沿用了這個名字。

下邊是在WHATWG文件中對WebSocket介面的定義:

enum BinaryType {“blob”,”arraybuffer”};

[Constructor(USVString url, optional (DOMString or sequence) protocols = []), Exposed=(Window,Worker)]

interface WebSocket : EventTarget {

readonly attribute USVString url;

// ready state

const unsigned short CONNECTING = 0;

const unsigned short OPEN = 1;

const unsigned short CLOSING = 2;

const unsigned short CLOSED = 3;

readonly attribute unsigned short readyState;

readonly attribute unsigned long long bufferedAmount;

// networking

attribute EventHandler onopen;

attribute EventHandler onerror;

attribute EventHandler onclose;

readonly attribute DOMString extensions;

readonly attribute DOMString protocol;

void close([Clamp] optional unsigned short code, optional USVString reason);

// messaging

attribute EventHandler onmessage;

attribute BinaryType binaryType;

void send(USVString data);

void send(Blob data);

void send(ArrayBuffer data);

void send(ArrayBufferView data);

};

8、再來看看Socket

Socket可以有很多意思,和IT較相關的本意大致是指在端到端的一個連線中,這兩個端叫做Socket。對於IT從業者來說,它往往指的是TCP/IP網路環境中的兩個連線端,大多數的API提供者(如作業系統,JDK)往往會提供基於這種概念的介面,所以對於開發者來說也往往是在說一種程式設計概念。同時,作業系統中程式間通訊也有Socket的概念,但這個Socket就不是基於網路傳輸層的協議了。

8.1 Unix中的Socket

作業系統中也有使用到Socket這個概念用來進行程式間通訊,它和通常說的基於TCP/IP的Socket概念十分相似,代表了在作業系統中傳輸資料的兩方,只是它不再基於網路協議,而是作業系統本身的檔案系統。

8.2 網路中的Socket

通常所說的Socket API,是指作業系統中(也可能不是作業系統)提供的對於傳輸層(TCP/UDP)抽象的介面。現行的Socket API大致都是遵循了BSD Socket規範(包括Windows)。這裡稱規範其實不太準確,規範其實是POSIX,但BSD Unix中對於Socket的實現被廣為使用,所以成為了實際的規範。如果你要使用HTTP來構建服務,那麼就不需要關心Socket,如果你想基於TCP/IP來構建服務,那麼Socket可能就是你會接觸到的API。

▲ 在TCP/IP網路中HTTP的位置

從上圖中可以看到,HTTP是基於傳輸層的TCP協議的,而Socket API也是,所以只是從使用上說,可以認為Socket和HTTP類似(但一個是成文的網際網路協議,一個是一直沿用的一種程式設計概念),是對於傳輸層協議的另一種直接使用,因為按照設計,網路對使用者的介面都應該在應用層。

8.3 Socket名稱的由來

和很多其他Internet上的事物一樣,Socket這個名稱來自於大名鼎鼎的ARPANET(Advanced Research Projects Agency),早期ARPANET中的Socket指的是一個源或者目的地址——大致就是今天我們所說的IP地址和埠號。最早的時候一個Socket指的是一個40位的數字(RFC33中說明了此用法,但在RFC36中並沒有明確地說使用40位數字來標識一個地址),其中前32為指向的地址(socket number,大致相當於IP),後8位為傳送資料的源(link,大致相當於埠號)。對他們的叫法有很多的版本,這裡列舉的並不嚴謹。

8.4 埠號的野史

隨著ARPANET的發展,後來(RFC433,Socket Number List)socket number被明確地定義為一個40位的數字,其中後8位被用來制定某個特定的應用使用(比如1是Telnet)。這8位數有很多名字:link、socket name、AEN(another eight number,看到這個名字我也是醉了),工程師逗逼起來也是挺拼的。

後來在Internet的規範制定中,才真正的用起了port number這個詞。至於為什麼埠號是16位的,我想可能有兩個原因,一是對於當時的工程師來說,如果每個埠號來標識一個程式,65535個埠號也差不多夠用了。二可能是為了對齊吧,_!!。

8.5 Socket原本的意思

在上邊提到的歷史中使用到的Socket,包括TCP文件中使用到的Socket,其實指的是網路傳輸中的一端,是一個虛擬化的概念。

9、Socket 與 WebSocket 的關係

正如上節所述:Socket 其實並不是一個協議,它工作在 OSI 模型會話層(第5層),是為了方便大家直接使用更底層協議(一般是TCPUDP)而存在的一個抽象層。

最早的一套 Socket API 是Berkeley sockets,採用 C 語言實現。它是 Socket 的事實標準,POSIX sockets 是基於它構建的,多種程式語言都遵循這套 API,在 JAVA、Python 中都能看到這套 API 的影子。

下面摘錄一段更容易理解的文字(來自 http和socket之長連線和短連線區別):

Socket是應用層與TCP/IP協議族通訊的中間軟體抽象層,它是一組介面。在設計模式中,Socket其實就是一個門面模式,它把複雜的TCP/IP協議族隱藏在Socket介面後面,對使用者來說,一組簡單的介面就是全部,讓Socket去組織資料,以符合指定的協議。

主機 A 的應用程式要能和主機 B 的應用程式通訊,必須通過 Socket 建立連線,而建立 Socket 連線必須需要底層 TCP/IP 協議來建立 TCP 連線。建立 TCP 連線需要底層 IP 協議來定址網路中的主機。我們知道網路層使用的 IP 協議可以幫助我們根據 IP 地址來找到目標主機,但是一臺主機上可能執行著多個應用程式,如何才能與指定的應用程式通訊就要通過 TCP 或 UPD 的地址也就是埠號來指定。這樣就可以通過一個 Socket 例項唯一代表一個主機上的一個應用程式的通訊鏈路了。

而 WebSocket 則不同,它是一個完整的應用層協議,包含一套標準的 API

所以,從使用上來說,WebSocket 更易用,而 Socket 更靈活。

9、最後提一下 HTML5 與 WebSocket 的關係

WebSocket APIHTML5標準的一部分, 但這並不代表 WebSocket 一定要用在 HTML 中,或者只能在基於瀏覽器的應用程式中使用。

實際上,許多語言、框架和伺服器都提供了 WebSocket 支援,例如:

1)基於 C 的libwebsocket.org

2)基於 Node.js 的Socket.io

3)基於 Python 的ws4py

4)基於 C++ 的WebSocket++

5)Apache 對 WebSocket 的支援:Apache Module mod_proxy_wstunnel

6)Nginx 對 WebSockets 的支援:NGINX as a WebSockets ProxyNGINX Announces Support for WebSocket ProtocolWebSocket proxying

7)lighttpd 對 WebSocket 的支援:mod_websocket

附錄:其它Web端即時通訊技術文章

新手入門貼:史上最全Web端即時通訊技術原理詳解

Web端即時通訊技術盤點:短輪詢、Comet、Websocket、SSE

SSE技術詳解:一種全新的HTML5伺服器推送事件技術

Comet技術詳解:基於HTTP長連線的Web端實時通訊技術

新手快速入門:WebSocket簡明教程

socket.io實現訊息推送的一點實踐及思路

LinkedIn的Web端即時通訊實踐:實現單機幾十萬條長連線

Web端即時通訊技術的發展與WebSocket、Socket.io的技術實踐

Web端即時通訊安全:跨站點WebSocket劫持漏洞詳解(含示例程式碼)

開源框架Pomelo實踐:搭建Web端高效能分散式IM聊天伺服器

使用WebSocket和SSE技術實現Web端訊息推送

詳解Web端通訊方式的演進:從Ajax、JSONP 到 SSE、Websocket

MobileIMSDK-Web的網路層框架為何使用的是Socket.io而不是Netty?

>>更多同類文章 ……

(本文同步釋出於:http://www.52im.net/thread-1273-1-1.html


相關文章