搜尋
首頁web前端js教程JavaScript之WebSocket技術詳解

JavaScript之WebSocket技術詳解

Dec 06, 2016 pm 02:56 PM
javascript

概述

HTTP協定是一種無狀態協議,伺服器端本身不具有識別客戶端的能力,必須藉助外部機制,例如session和cookie,才能與特定客戶端保持對話。這多多少少帶來一些不便,尤其在伺服器端與客戶端需要持續交換資料的場合(例如網路聊天),更是如此。為了解決這個問題,HTML5提出了瀏覽器的WebSocket API。

WebSocket的主要作用是,允許伺服器端與客戶端進行全雙工(full-duplex)的通訊。舉例來說,HTTP協定有點像發電子郵件,發出後必須等待對方回信;WebSocket則是像打電話,伺服器端和客戶端可以同時向對方發送數據,它們之間存著一條持續打開的數據通道。

WebSocket協定完全可以取代Ajax方法,用來向伺服器端發送文字和二進位數據,而且還沒有「同域限制」。

WebSocket不使用HTTP協議,而是使用自己的協定。瀏覽器發出的WebSocket請求類似下面的樣子:

GET / HTTP/1.1
Connection: Upgrade
Upgrade: websocket
Host: example.com
Origin: null
Sec-WebSocket-MWA30000nF775 Sec-WebSocket-Version: 13
上面的頭目資訊顯示,有一個HTTP頭是Upgrade。 HTTP1.1協定規定,Upgrade頭資訊表示將通訊協定從HTTP/1.1轉向該項所指定的協定。 「Connection: Upgrade」就表示瀏覽器通知伺服器,如果可以,就升級到webSocket協定。 Origin用於驗證瀏覽器網域是否在伺服器授權的範圍內。 Sec-WebSocket-Key則是用來握手協定的金鑰,是base64編碼的16位元組隨機字串。

伺服器端的WebSocket回應則是

HTTP/1.1 101 Switching Protocols

Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: fFBooB7FAmLloBRRkk-TR30503050503050000545FFF45:TFF例如TFoneT 只是TRWkalk Sec-WebSocket-Location: ws: //example.com/


伺服器端同樣用「Connection: Upgrade」通知瀏覽器,需要改變協定。 Sec-WebSocket-Accept是伺服器在瀏覽器提供的Sec-WebSocket-Key字串後面,加入「258EAFA5-E914-47DA-95CA-C5AB0DC85B11」 字串,然後再取sha-1的hash值。瀏覽器將對這個值進行驗證,以證明確實是目標伺服器回應了webSocket請求。 Sec-WebSocket-Location表示進行通訊的WebSocket網址。

請注意,WebSocket協定用ws表示。此外,還有wss協議,表示加密的WebSocket協議,對應HTTPs協議。

完成握手以後,WebSocket協定就在TCP協定之上,開始傳送資料。

WebSocket協定需要伺服器支持,目前比較流行的實作是基於node.js的socket.io,更多的實作可參考Wikipedia。至於瀏覽器端,目前主流瀏覽器都支援WebSocket協定(包括IE 10+),僅有的例外是手機端的Opera Mini和Android Browser。

客戶端

瀏覽器端對WebSocket協定的處理,無非就是三件事:

建立連接和斷開連接

發送資料和接收資料

處理錯誤



建立連接和斷開連接,客戶端要檢查瀏覽器是否支援WebSocket,使用的方法是查看window物件是否具有WebSocket屬性。

if(window.WebSocket != undefined) {
 
 // WebSocket代码
 
}

   

然後,開始與伺服器建立連接(這裡假定伺服器就是本機的1740端口,需要使用ws協定)。

if(window.WebSocket != undefined) {
 
 var connection = new WebSocket('ws://localhost:1740');
 
}

   

建立連接以後的WebSocket實例物件(即上面程式碼中的connection),有一個readyState屬性,表示目前的狀態,可以取4個值:

0: 1
成功

2:正在關閉

3: 連線關閉

握手協定成功以後,readyState就從0變為1,並觸發open事件,這時就可以向伺服器發送訊息了。我們可以指定open事件的回呼函數。


connection.onopen = wsOpen;

function wsOpen (event) {
console.log(‘Connected to: ‘ + event.currentTarget.URL);
}

   

關閉WebSocket連接,會觸發close事件。

connection.onclose = wsClose;

function wsClose () {
console.log(“Closed”);
}
 
connection.close();

   

發送資料和接收資料

連線建立後,客戶端透過send方法傳送資料到伺服器端。

connection.send(message);

除了發送字串,也可以使用 Blob 或 ArrayBuffer 物件發送二進位資料。

// 使用ArrayBuffer发送canvas图像数据
 
var img = canvas_context.getImageData(0, 0, 400, 320);
 
var binary = new Uint8Array(img.data.length);
 
for (var i = 0; i < img.data.length; i++) {
 
 binary[i] = img.data[i];
 
}
 
connection.send(binary.buffer);
// 使用Blob发送文件
var file = document.querySelector(‘input[type=”file”]&#39;).files[0];
connection.send(file);

   


客戶端收到伺服器傳送的數據,會觸發message事件。可以透過定義message事件的回呼函數,來處理服務端所傳回的資料。

connection.onmessage = wsMessage;

function wsMessage (event) {
console.log(event.data);
}

   

上面程式碼的回呼函數wsMessage的參數為事件物件event,該物件的data屬性包含了伺服器傳回的資料。

如果接收的是二進位數據,需要將連接物件的格式設為blob或arraybuffer。

connection.binaryType = &#39;arraybuffer&#39;;
 
connection.onmessage = function(e) {
 console.log(e.data.byteLength); // ArrayBuffer对象有byteLength属性
};

   

處理錯誤

如果出現錯誤,瀏覽器會觸發WebSocket實例物件的error事件。

connection.onerror = wsError;

function wsError(event) {
console.log(“Error: “ + event.data);
}

   

服务器端

服务器端需要单独部署处理WebSocket的代码。下面用node.js搭建一个服务器环境。

var http = require(&#39;http&#39;);
 
var server = http.createServer(function(request, response) {});

   


假设监听1740端口。

server.listen(1740, function() {
 
 console.log((new Date()) + &#39; Server is listening on port 1740&#39;);
 
});


接着启动WebSocket服务器。这需要加载websocket库,如果没有安装,可以先使用npm命令安装。

var WebSocketServer = require(&#39;websocket&#39;).server;
 
var wsServer = new WebSocketServer({
 
 httpServer: server
 
});
   
WebSocket服务器建立request事件的回调函数。
var connection;wsServer.on(‘request&#39;, function(req){
connection = req.accept(‘echo-protocol&#39;, req.origin);
});

   


上面代码的回调函数接受一个参数req,表示request请求对象。然后,在回调函数内部,建立WebSocket连接connection。接着,就要对connection的message事件指定回调函数。

wsServer.on(‘request&#39;, function(r){
 
 connection = req.accept(‘echo-protocol&#39;, req.origin);

  

<span class="nx">connection</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="s1">&#39;message&#39;</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
 <span class="kd">var</span> <span class="nx">msgString</span> <span class="o">=</span> <span class="nx">message</span><span class="p">.</span><span class="nx">utf8Data</span><span class="p">;</span>
 <span class="nx">connection</span><span class="p">.</span><span class="nx">sendUTF</span><span class="p">(</span><span class="nx">msgString</span><span class="p">);</span>
<span class="p">});</span>
});

   


最后,监听用户的disconnect事件。

connection.on(&#39;close&#39;, function(reasonCode, description) {
 
 console.log(connection.remoteAddress + &#39; disconnected.&#39;);
 
});

   


使用ws模块,部署一个简单的WebSocket服务器非常容易。

var WebSocketServer = require(&#39;ws&#39;).Server;
var wss = new WebSocketServer({ port: 8080 });
 
wss.on(&#39;connection&#39;, function connection(ws) {
 ws.on(&#39;message&#39;, function incoming(message) {
 console.log(&#39;received: %s&#39;, message);
 });
 
 ws.send(&#39;something&#39;);
});

   


Socket.io简介

Socket.io是目前最流行的WebSocket实现,包括服务器和客户端两个部分。它不仅简化了接口,使得操作更容易,而且对于那些不支持WebSocket的浏览器,会自动降为Ajax连接,最大限度地保证了兼容性。它的目标是统一通信机制,使得所有浏览器和移动设备都可以进行实时通信。

第一步,在服务器端的项目根目录下,安装socket.io模块。

$ npm install socket.io

第二步,在根目录下建立app.js,并写入以下代码(假定使用了Express框架)。

var app = require(&#39;express&#39;)();
var server = require(&#39;http&#39;).createServer(app);
var io = require(&#39;socket.io&#39;).listen(server);
 
server.listen(80);
 
app.get(&#39;/&#39;, function (req, res) {
 res.sendfile(__dirname + &#39;/index.html&#39;);
});

   


上面代码表示,先建立并运行HTTP服务器。Socket.io的运行建立在HTTP服务器之上。

第三步,将Socket.io插入客户端网页。


然后,在客户端脚本中,建立WebSocket连接。

var socket = io.connect('http://localhost:80');

由于本例假定WebSocket主机与客户端是同一台机器,所以connect方法的参数是http://localhost。接着,指定news事件(即服务器端发送news)的回调函数。

socket.on(&#39;news&#39;, function (data){
 console.log(data);
});

   


最后,用emit方法向服务器端发送信号,触发服务器端的anotherNews事件。

socket.emit('anotherNews');

请注意,emit方法可以取代Ajax请求,而on方法指定的回调函数,也等同于Ajax的回调函数。
第四步,在服务器端的app.js,加入以下代码。


io.sockets.on(&#39;connection&#39;, function (socket) {
 socket.emit(&#39;news&#39;, { hello: &#39;world&#39; });
 socket.on(&#39;anotherNews&#39;, function (data) {
 console.log(data);
 });
})
;


上面代码的io.sockets.on方法指定connection事件(WebSocket连接建立)的回调函数。在回调函数中,用emit方法向客户端发送数据,触发客户端的news事件。然后,再用on方法指定服务器端anotherNews事件的回调函数。

不管是服务器还是客户端,socket.io提供两个核心方法:emit方法用于发送消息,on方法用于监听对方发送的消息。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript框架:為現代網絡開發提供動力JavaScript框架:為現代網絡開發提供動力May 02, 2025 am 12:04 AM

JavaScript框架的強大之處在於簡化開發、提升用戶體驗和應用性能。選擇框架時應考慮:1.項目規模和復雜度,2.團隊經驗,3.生態系統和社區支持。

JavaScript,C和瀏覽器之間的關係JavaScript,C和瀏覽器之間的關係May 01, 2025 am 12:06 AM

引言我知道你可能會覺得奇怪,JavaScript、C 和瀏覽器之間到底有什麼關係?它們之間看似毫無關聯,但實際上,它們在現代網絡開發中扮演著非常重要的角色。今天我們就來深入探討一下這三者之間的緊密聯繫。通過這篇文章,你將了解到JavaScript如何在瀏覽器中運行,C 在瀏覽器引擎中的作用,以及它們如何共同推動網頁的渲染和交互。 JavaScript與瀏覽器的關係我們都知道,JavaScript是前端開發的核心語言,它直接在瀏覽器中運行,讓網頁變得生動有趣。你是否曾經想過,為什麼JavaScr

node.js流帶打字稿node.js流帶打字稿Apr 30, 2025 am 08:22 AM

Node.js擅長於高效I/O,這在很大程度上要歸功於流。 流媒體匯總處理數據,避免內存過載 - 大型文件,網絡任務和實時應用程序的理想。將流與打字稿的類型安全結合起來創建POWE

Python vs. JavaScript:性能和效率注意事項Python vs. JavaScript:性能和效率注意事項Apr 30, 2025 am 12:08 AM

Python和JavaScript在性能和效率方面的差異主要體現在:1)Python作為解釋型語言,運行速度較慢,但開發效率高,適合快速原型開發;2)JavaScript在瀏覽器中受限於單線程,但在Node.js中可利用多線程和異步I/O提升性能,兩者在實際項目中各有優勢。

JavaScript的起源:探索其實施語言JavaScript的起源:探索其實施語言Apr 29, 2025 am 12:51 AM

JavaScript起源於1995年,由布蘭登·艾克創造,實現語言為C語言。 1.C語言為JavaScript提供了高性能和系統級編程能力。 2.JavaScript的內存管理和性能優化依賴於C語言。 3.C語言的跨平台特性幫助JavaScript在不同操作系統上高效運行。

幕後:什麼語言能力JavaScript?幕後:什麼語言能力JavaScript?Apr 28, 2025 am 12:01 AM

JavaScript在瀏覽器和Node.js環境中運行,依賴JavaScript引擎解析和執行代碼。 1)解析階段生成抽象語法樹(AST);2)編譯階段將AST轉換為字節碼或機器碼;3)執行階段執行編譯後的代碼。

Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Safe Exam Browser

Safe Exam Browser

Safe Exam Browser是一個安全的瀏覽器環境,安全地進行線上考試。該軟體將任何電腦變成一個安全的工作站。它控制對任何實用工具的訪問,並防止學生使用未經授權的資源。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器