說說 WebSocket 和 Socket 及 Http 的區別?

原文:juejin.cn/post/6942358900171603975

Socket 是什麼?

TCP/IP 和 HTTP 協議的關係是: “我們在傳輸數據時,可以只使用 (傳輸層)TCP/IP 協議,但是那樣的話,如果沒有應用層,便無法識別數據內容。如果想要使傳輸的數據有意義,則必須使用到應用層協議。應用層協議有很多,比如 HTTP、FTP、TELNET 等,也可以自己定義應用層協議。WEB 使用 HTTP 協議作應用層協議,以封裝 HTTP 文本信息,然後使用 TCP/IP 做傳輸層協議將它發到網絡上。”

Socket 是什麼呢,實際上 socket 是對 TCP/IP 協議的封裝,Socket 本身並不是協議,而是一個調用接口 (API)。通過 Socket,我們才能使用 TCP/IP 協議。

Socket 跟 TCP/IP 協議關係是: “TCP/IP 只是一個協議棧,就像操作系統的運行機制一樣,必須要具體實現,同時還要提供對外的操作接口。這個就像操作系統會提供標準的編程接口,比如 win32 編程接口一樣,TCP/IP 也要提供可供程序員做網絡開發所用的接口,這就是 Socket 編程接口。”

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

WebSocket 協議的來源:

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

WebSocket 協議的開篇就說,本協議的目的是爲了解決基於瀏覽器的程序需要拉取資源時必須發起多個 HTTP 請求和長時間的輪訓的問題…… 而創建的。

WebSocket 和 Socket 的區別?

兩者沒什麼關係,就像雷鋒跟雷鋒塔一樣。

爲什麼要使用 Websocket?

WebSocket 的目的就是解決網絡傳輸中的雙向通信的問題,HTTP1.1 默認使用持久連接(persistent connection),在一個 TCP 連接上也可以傳輸多個Request/Response消息對,但是 HTTP 的基本模型還是一個 Request 對應一個 Response。

這在雙向通信(客戶端要向服務器傳送數據,同時服務器也需要實時的向客戶端傳送信息,一個聊天系統就是典型的雙向通信)時一般會使用這樣幾種解決方案:

Websocket 協議內容

WebSocket 的目的是取代 HTTP 在雙向通信場景下的使用,而且它的實現方式有些也是基於 HTTP 的(WS 的默認端口是 80 和 443)。現有的網絡環境(客戶端、服務器、網絡中間人、代理等)對 HTTP 都有很好的支持,所以這樣做可以充分利用現有的 HTTP 的基礎設施,有點向下兼容的意味。

WS 協議有兩部分組成:握手和數據傳輸。

握手

使用 Http 進行實現。由客戶端使用 http 的方式發起握手請求,服務端接請求後,將當前正在使用的連接(TCP)的協議,由 http 協議切換爲 websocket 協議。

握手請求頭會帶有 Upgrade 參數用於升級協議類型:

Upgrade: upgrade 是 HTTP1.1 中用於定義轉換協議的 header 域。它表示,如果服務器支持的話,客戶端希望使用現有的「網絡層」已經建立好的這個「連接(此處是 TCP 連接)」,切換到另外一個「應用層」(此處是 WebSocket)協議。

Upgrade 擴展:Upgrade 是 HTTP 中用來進行協議升級的頭域,在擴展的協議內容中,客戶端發起的協議轉換的方式更多,同時服務器也可以選擇不接受客戶端的協議升級請求;服務端也可以發起協議升級。

請求 uri 格式:

  ws-URI = "ws:" "//" host [ ":" port ] path [ "?" query ]
  wss-URI = "wss:" "//" host [ ":" port ] path [ "?" query ]

  host = <host, defined in [RFC3986], Section 3.2.2>
  port = <port, defined in [RFC3986], Section 3.2.3>
  path = <path-abempty, defined in [RFC3986], Section 3.3>
  query = <query, defined in [RFC3986], Section 3.4>
數據傳輸

服務端接收握手請求後,回覆 response 消息,一旦這個握手回覆發出去,服務端就認爲此 WebSocket 連接已經建立成功,處於 OPEN 狀態。它就可以開始發送數據了。

WebSocket 中所有發送的數據使用幀的形式發送。客戶端發送的數據幀都要經過掩碼處理,服務端發送的所有數據幀都不能經過掩碼處理。否則對方需要發送關閉幀。

一個幀包含一個幀類型的標識碼,一個負載長度,和負載。負載包括擴展內容和應用內容。

WebSocket 和 HTTP 的對比

相同點
不同點
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/-hSMw3rp7uPhwjgwdqt_7w