首頁  >  文章  >  websocket和socket的差別是什麼

websocket和socket的差別是什麼

青灯夜游
青灯夜游原創
2020-12-24 11:25:1439791瀏覽

區別:Socket是TCP/IP網路的API,是為了方便使用TCP或UDP而抽像出來的一層,是位於應用層和傳輸控制層之間的一組介面;而WebSocket則是一個典型的應用層協定。

websocket和socket的差別是什麼

本教學操作環境:windows7系統、Dell G3電腦。

相關推薦:《程式設計影片

WebSocket介紹與原理

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

——百度百科

目的:即時通訊,替代輪詢

網站上的即時通訊是很常見的,例如網頁的QQ,聊天系統等。依照以往的技術能力通常是採用輪詢、Comet技術解決。

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

缺點:會導致過多不必要的請求,浪費流量和伺服器資源,每一次請求、應答,都浪費了一定流量在相同的頭部資訊上

然而WebSocket的出現可以彌補這一缺點。在WebSocket中,只需要伺服器和瀏覽器透過HTTP協定進行一個握手的動作,然後單獨建立一條TCP的通訊通道進行資料的傳送。

原理

WebSocket同HTTP一樣也是應用層的協議,但是它是一種雙向通訊協議,是建立在TCP之上的。

連接過程 —— 握手過程

  • 1. 瀏覽器、伺服器建立TCP連接,三次握手。這是通訊的基礎,傳輸控制層,若失敗後續都不執行。
  • 2. TCP連線成功後,瀏覽器透過HTTP協定向伺服器傳送WebSocket支援的版本號等資訊。 (開始前的HTTP握手)
  • 3. 伺服器收到客戶端的握手請求後,同樣採用HTTP協定回饋資料。
  • 4. 當收到了連接成功的訊息後,透過TCP通道進行傳輸通訊。

WebSocket與HTTP的關係

相同點

  • 1. 都是一樣基於TCP的,都是可靠性傳輸協定。
  • 2. 都是應用層協定。

不同點

  • 1. WebSocket是雙向通訊協議,模擬Socket協議,可以雙向發送或接受訊息。 HTTP是單向的。
  • 2. WebSocket是需要握手才能建立連線的。

 聯繫

WebSocket在建立握手時,資料是透過HTTP傳送的。但是建立之後,真正傳輸時候是不需要HTTP協定的。

WebSocket與Socket的關係

Socket其實不是協議,而是為了方便使用TCP或UDP而抽像出來的一層,是位於應用層和傳輸控制層之間的一組介面。

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

當兩台主機通訊時,必須透過Socket連接,Socket則利用TCP/IP協定建立TCP連線。 TCP連線則更依賴底層的IP協定,IP協定的連線則依賴連結層等較低層次。

WebSocket則是典型的應用層協定。

區別

Socket是傳輸控制層協議,WebSocket是應用層協議。

HTML5與WebSocket的關係

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

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

  • * 基於C 的libwebsocket.org
  • * 基於Node.js 的Socket.io
  • * 基於Python 的ws4py
  • * 基於C 的WebSocket
  • * Apache 對WebSocket 的支援: Apache Module mod_proxy_wstunnel
  • * Nginx 對WebSockets 的支援: NGINX as a WebSockets Proxy 、 NGINX Announces Support for WebSocket Protocol 、Web#Set projicing * lighttpd 對WebSocket 的支援:mod_websocket
##WebSocket 機制

##以下簡單介紹一下WebSocket 的原理及運作機制。 WebSocket 是 HTML5 一種新的協定。它實現了瀏覽器與伺服器全雙工通信,能更好的節省伺服器資源和頻寬並達到即時通訊,它建立在TCP 之上,同HTTP 一樣透過TCP 來傳輸數據,但是它和HTTP 最大不同是:

WebSocket 是一種雙向通訊協議,在建立連接後,WebSocket 伺服器和Browser/Client Agent 都能主動的向對方發送或接收數據,就像Socket 一樣;

WebSocket 需要類似TCP 的客戶端和伺服器端透過握手連接,連接成功後才能相互通訊。
  • 非WebSocket 模式傳統HTTP 用戶端與伺服器的互動如下圖所示:
  • 圖1. 傳統HTTP 請求回應用戶端伺服器互動圖

#使用WebSocket 模式客戶端與伺服器的互動如下圖:

图 1. 传统 HTTP 请求响应客户端服务器交互图圖2.WebSocket 請求回應客戶端伺服器互動圖

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

图 2.WebSocket 请求响应客户端服务器交互图我們再透過客戶端和服務端互動的封包看一下WebSocket 通訊與傳統HTTP 的不同:

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

清單1.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
http://localhost
:8080
Sec-WebSocket-Version: 13

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

服務端收到封包後回傳的資料格式類似:

清單2.WebSocket 服務端回應封包

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 API 也十分簡單,我們只需要實例化WebSocket,創建連接,然後服務端和客戶端就可以相互發送和響應訊息,在下文WebSocket 實現及案例分析部分,可以看到詳細的WebSocket API 及程式碼實作。

WebSocket 實作

如上文所述,WebSocket 的實作分為客戶端和服務端兩部分,客戶端(通常為瀏覽器)發出WebSocket 連線請求,服務端回應,實現類似TCP 握手的動作,從而在瀏覽器用戶端和WebSocket 服務端之間形成一條HTTP 長連線快速通道。兩者之間後續進行直接的資料互相傳送,不再需要發起連線和對應。

以下簡要描述 WebSocket 服務端 API 及客戶端 API。

WebSocket 服務端API

WebSocket 服務端在各個主流應用伺服器廠商中已基本獲得符合JEE JSR356 標準規範API 的支持,以下列舉了部分常見的商用及開源應用伺服器對WebSocket Server 端的支援情況:

表1.WebSocket 服務端支援

###IBMWebSphereWebSphere 8.0 以上版本支持,7.X 先前版本結合MQTT 支援類似的HTTP 長連接甲骨文WebLogicWebLogic 12c 支持,11g 及10g 版本透過HTTP Publish 支援類似的HTTP 長連線##微軟Apache 

以下我们使用 Tomcat7.0.5 版本的服务端示例代码说明 WebSocket 服务端的实现:

JSR356 的 WebSocket 规范使用 javax.websocket.*的 API,可以将一个普通 Java 对象(POJO)使用 @ServerEndpoint 注释作为 WebSocket 服务器的端点,代码示例如下:

清单 3.WebSocket 服务端 API 示例

 @ServerEndpoint("/echo")
 public class EchoEndpoint {

 @OnOpen
 public void onOpen(Session session) throws IOException {
 //以下代码省略...
 }
 
 @OnMessage
 public String onMessage(String message) {
 //以下代码省略...
 }

 @Message(maxMessageSize=6)
 public void receiveMessage(String s) {
 //以下代码省略...
 } 

 @OnError
 public void onError(Throwable t) {
 //以下代码省略...
 }
 
 @OnClose
 public void onClose(Session session, CloseReason reason) {
 //以下代码省略...
 } 
 
 }

代码解释:

上文的简洁代码即建立了一个 WebSocket 的服务端,@ServerEndpoint("/echo") 的 annotation 注释端点表示将 WebSocket 服务端运行在 ws://[Server 端 IP 或域名]:[Server 端口]/websockets/echo 的访问端点,客户端浏览器已经可以对 WebSocket 客户端 API 发起 HTTP 长连接了。

使用 ServerEndpoint 注释的类必须有一个公共的无参数构造函数,@onMessage 注解的 Java 方法用于接收传入的 WebSocket 信息,这个信息可以是文本格式,也可以是二进制格式。

OnOpen 在这个端点一个新的连接建立时被调用。参数提供了连接的另一端的更多细节。Session 表明两个 WebSocket 端点对话连接的另一端,可以理解为类似 HTTPSession 的概念。

OnClose 在连接被终止时调用。参数 closeReason 可封装更多细节,如为什么一个 WebSocket 连接关闭。

更高级的定制如 @Message 注释,MaxMessageSize 属性可以被用来定义消息字节最大限制,在示例程序中,如果超过 6 个字节的信息被接收,就报告错误和连接关闭。

注意:早期不同应用服务器支持的 WebSocket 方式不尽相同,即使同一厂商,不同版本也有细微差别,如 Tomcat 服务器 7.0.5 以上的版本都是标准 JSR356 规范实现,而 7.0.2x/7.0.3X 的版本使用自定义 API (WebSocketServlet 和 StreamInbound, 前者是一个容器,用来初始化 WebSocket 环境;后者是用来具体处理 WebSocket 请求和响应,详见案例分析部分),且 Tomcat7.0.3x 与 7.0.2x 的 createWebSocketInbound 方法的定义不同,增加了一个 HttpServletRequest 参数,使得可以从 request 参数中获取更多 WebSocket 客户端的信息,如下代码所示:

清单 4.Tomcat7.0.3X 版本 WebSocket API

public class EchoServlet extends WebSocketServlet {
@Override
protected StreamInbound createWebSocketInbound(String subProtocol,
HttpServletRequest request) {
 //以下代码省略....
return new MessageInbound() {
 //以下代码省略....
}
protected void onBinaryMessage(ByteBuffer buffer)
throws IOException {
 //以下代码省略...
}
protected void onTextMessage(CharBuffer buffer) throws IOException {
 getWsOutbound().writeTextMessage(buffer);
 //以下代码省略...
}
};
}
}

因此选择 WebSocket 的 Server 端重点需要选择其版本,通常情况下,更新的版本对 WebSocket 的支持是标准 JSR 规范 API,但也要考虑开发易用性及老版本程序移植性等方面的问题,如下文所述的客户案例,就是因为客户要求统一应用服务器版本所以使用的 Tomcat 7.0.3X 版本的 WebSocketServlet 实现,而不是 JSR356 的 @ServerEndpoint 注释端点。

WebSocket 客户端 API

对于 WebSocket 客户端,主流的浏览器(包括 PC 和移动终端)现已都支持标准的 HTML5 的 WebSocket API,这意味着客户端的 WebSocket JavaScirpt 脚本具备良好的一致性和跨平台特性,以下列举了常见的浏览器厂商对 WebSocket 的支持情况:

表 2.WebSocket 客户端支持

廠商應用程式伺服器備註
#IISIIS 7.0支持
Tomcat#Tomcat 7.0.5+支持,7.0.2X 及7.0.3X 透過自訂API 支援
JettyJetty 7.0+支援
浏览器支持情况
ChromeChrome version 4+支持
FirefoxFirefox version 5+支持
IEIE version 10+支持
SafariIOS 5+支持
Android BrowerAndroid 4.5+支持

客户端 WebSocket API 基本上已经在各个主流浏览器厂商中实现了统一,因此使用标准 HTML5 定义的 WebSocket 客户端的 JavaScript API 即可,当然也可以使用业界满足 WebSocket 标准规范的开源框架,如 Socket.io。

以下以一段代码示例说明 WebSocket 的客户端实现:

清单 5.WebSocket 客户端 API 示例

var ws = new WebSocket(“ws://echo.websocket.org”); 
 ws.onopen = function(){ws.send(“Test!”); }; 
 ws.onmessage = function(evt){console.log(evt.data);ws.close();}; 
 ws.onclose = function(evt){console.log(“WebSocketClosed!”);}; 
 ws.onerror = function(evt){console.log(“WebSocketError!”);};

第一行代码是在申请一个 WebSocket 对象,参数是需要连接的服务器端的地址,同 HTTP 协议开头一样,WebSocket 协议的 URL 使用 ws://开头,另外安全的 WebSocket 协议使用 wss://开头。

第二行到第五行为 WebSocket 对象注册消息的处理函数,WebSocket 对象一共支持四个消息 onopen, onmessage, onclose 和 onerror,有了这 4 个事件,我们就可以很容易很轻松的驾驭 WebSocket。

当 Browser 和 WebSocketServer 连接成功后,会触发 onopen 消息;如果连接失败,发送、接收数据失败或者处理数据出现错误,browser 会触发 onerror 消息;当 Browser 接收到 WebSocketServer 发送过来的数据时,就会触发 onmessage 消息,参数 evt 中包含 Server 传输过来的数据;当 Browser 接收到 WebSocketServer 端发送的关闭连接请求时,就会触发 onclose 消息。我们可以看出所有的操作都是采用异步回调的方式触发,这样不会阻塞 UI,可以获得更快的响应时间,更好的用户体验。

想要查阅更多相关文章,请访问PHP中文网!!

以上是websocket和socket的差別是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn