HTML5 WebSocket技術使用詳解

本文爲大家詳細介紹了WebSocket技術使用方法,WebSocket是HTML5開始提供的一種瀏覽器與服務器間進行全雙工通訊的網絡技術

WebSocket

WebSocket是HTML5開始提供的一種瀏覽器與服務器間進行全雙工通訊的網絡技術。

現很多網站爲了實現即時通訊,所用的技術都是輪詢(polling)。輪詢是在特定的的時間間隔(如每1秒),由瀏覽器對服務器發出HTTP請求,然後由服務器返回最新的數據給客服端的瀏覽器,這種方式有一個很大的弊端,就是會佔用很多的帶寬。

最新的輪詢效果是Comet – 用了AJAX。但這種技術雖然可達到全雙工通信,但依然需要發出請求。

使用WebSocket,瀏覽器和服務器只需要要做一個握手的動作,然後,瀏覽器和服務器之間就形成了一條快速通道,兩者之間就直接可以數據互相傳送。而且它爲我們實現即時服務帶來了兩大好處:

節省資源:互相溝通的Header是很小的-大概只有 2 Bytes。
推送信息:不需要客戶端請求,服務器可以主動傳送數據給客戶端。

socket.io

Socket.IO是一個WebSocket庫,包括了客戶端的js和服務器端的nodejs,它的目標是構建可以在不同瀏覽器和移動設備上使用的實時應用。

socket.io的特點

易用性:socket.io封裝了服務端和客戶端,使用起來非常簡單方便。

跨平臺:socket.io支持跨平臺,這就意味着你有了更多的選擇,可以在自己喜歡的平臺下開發實時應用。

自適應:它會自動根據瀏覽器從WebSocket、AJAX長輪詢、Iframe流等等各種方式中選擇最佳的方式來實現網絡實時應用,非常方便和人性化,而且支持的瀏覽器最低達IE5.5。

WebSocket 安裝部署

npm install socket.io

服務監聽

socket.io的服務端啓動非常的簡單,引用socket.io模塊。

var io = require('socket.io');

然後調用listen函數,傳入監聽的端口號,開始服務監聽。啓用了80端口用於測試:

var io = require('socket.io')(80);

註冊事件

io.on('connection', function (socket) {
  socket.on('disconnect', function () {

  })
})

connection事件在客戶端成功連接到服務端時觸發,有了這個事件,我們可以隨時掌握用戶連接到服務端的信息。

當客戶端成功建立連接時,在connection事件的回調函數中,我們還是可以爲socket註冊一些常用的事件,如:disconnect事件,它在客戶端連接斷開是觸發,這時候我就知道用戶已經離開了。

WebSocket 啓動服務

目前爲止,我們已經搭建好了一個最簡單的socket服務器,爲了在瀏覽器中能夠訪問到我們的服務,我們還需要在服務端搭建一個簡單的web服務器,讓瀏覽器能夠訪問我們的客戶端頁面。

爲了便捷,我們選用node.js中常用的express框架來實現web服務,示例如下:

var express = require('express');
var app = express();
app.get('/', function (req, res) {
  res.status(200).send('成功連接!')
});
var server = require('http').createServer(app);
var io = require('socket.io')(server);
io.on('connection', function (socket) {

});
server.listen(80);

WebSocket 客戶端引用

服務端構建完畢,下面看一看客戶端應該如何使用。

服務端運行後會在根目錄動態生成socket.io的客戶端js文件,客戶端可以通過固定路徑/socket.io/socket.io.js添加引用。

首先添加網頁index.html,並在網頁中引用客戶端js文件:

<script src="//cdn.bootcss.com/socket.io/2.0.2/socket.io.js"></script>

WebSocket 連接服務

當客戶端成功加載socket.io客戶端文件後會獲取到一個全局對象io,我們將通過io.connect函數來向服務端發起連接請求。

var socket = io.connect('/');
socket.on('connect',function(){
  //連接成功
});
socket.on('disconnect',function(data){
  //連接斷開
});

connect函數可以接受一個url參數,url可以socket服務的http完整地址,也可以是相對路徑,如果省略則表示默認連接當前路徑。與服務端類似,客戶端也需要註冊相應的事件來捕獲信息,不同的是客戶端連接成功的事件是connect。

瞭解了客戶端如何使用,下面我們創建網頁index.html,並添加如下內容(保存):

<html>
<head>
  <script src="//cdn.bootcss.com/socket.io/2.0.2/socket.io.js"></script>
  <script>
    window.onload = function(){
      var socket = io.connect('/');
      socket.on('connect',function(){
        document.write('連接成功!');
      });
    };
  </script>
</head>
<body>
</body>
</html>

頁面添加完畢還要記得在服務端app.js中爲它添加路由,讓我們可以訪問測試網頁:

app.get('/index',function(req,res){
  res.sendFile('index.html',{root:__dirname});
});

WebSocket 實時通訊

服務端和客戶端都構建完畢了,下面開始發送消息。

當我們成功建立連接後,我們可以通過socket對象的send函數來互相發送消息,示例-客戶端向服務端發送消息(index.html):

var socket = io.connect('/');
socket.on('connect',function(){
  //客戶端連接成功後發送消息'hello world!'
  socket.send('hello world!');
});
socket.on('message',function(data){
  alert(data);
});

連接成功後,我們向服務端發送消息hello world!,還爲socket註冊了message事件,它是send函數對應的接收消息的事件,當服務端向客戶端send消息時,我們就可以在message事件中接收到發送過來的消息。

服務端向客戶端發送消息也可以通過send的方式,示例 - 服務端向客戶端發送消息(app.js):

var io = require('scoket.io');
io.on('connection', function (socket) {
  socket.send('Hello World!');
  socket.on('message', function (data) {
    console.log(data);
  })
});

與客戶端相同,服務端也需要爲socket註冊message事件來接收客戶端發送過來的消息。

WebSocket 發送信息

socket.io既然是用來實現通訊的,那麼如何發送、接收信息纔是根本。

在socket.io中,emit函數用於發送數據,我們使用send的方式實現了信息的互發,其實send函數只是emit的封裝,實際上還是使用了emit,且看send函數是如何實現的:

function send(){
 var args = toArray(arguments);
 args.unshift('message');
 this.emit.apply(this, args);
 return this;
}

在send函數中,獲取到原來的參數,並在原來的基礎上插入了一個參數message,然後調用了emit函數。通過send函數的實現,我們也學會了emit函數的用法,它有多個參數,第一個參數是事件名稱,在接收端註冊該事件就可以接收到發送過去的信息,事件名稱可以自由定義,在不同的場景下,我們可以定義不同的事件來接收消息。第二個參數纔是發送的數據。瞭解清楚了工作原理,下面來將send替換成emit函數發送信息:

//app.js
io.on('connection',function(socket){
   socket.emit('message','連接成功!');
   socket.on('message',function(data){
  });
});

WebSocket 服務端事件

事件監聽是實現通訊的基礎,因此充分了解socket.io的事件,學習如何在正確的時候使用它們至關重要。在一些關鍵的的狀態下,socket.io可以註冊相應的事件,通過事件監聽,我們可以在這些事件中作出反應,常用的事件如下:

connection——客戶端成功連接到服務器。

message——捕獲客戶端send信息。。

disconnect——客戶端斷開連接。

error——發生錯誤。

WebSocket 客戶端

較服務端而言,客戶端提供更多的監聽事件,在實時應用中,我們可以爲這些事件註冊監聽並作出反應,例如:connect提示用戶連接成功,disconnect時提示用戶停止服務等等。

connection——成功連接到服務器。

connecting——正在連接。

disconnect——斷開連接。

connect_failed——連接失敗。

error——連接錯誤。

message——監聽服務端send的信息。

reconnect_failed——重新連接失敗。

reconnect——重新連接成功。

reconnecting——正在重連。

那麼客戶端socket發起連接時的順序是怎麼樣的呢?當第一次連接時,事件觸發順序爲: connecting → connect;

當失去連接時,事件觸發順序爲:disconnect → reconnecting → connecting → reconnect → connect。

WebSocket 命名空間

命名空間着實是一個非常實用好用的功能。我們可以通過命名空間,劃分出不同的房間,在房間裏的廣播和通信都不會影響到房間以外的客戶端。

那麼如何創建房間呢?在服務端,通過of("")的方式來劃分新的命名空間:

io.of('chat').on('connection',function(socket){
});

示例中,我們創建一個名爲chat的房間,客戶端可以通過如下方式連接到指定的房間:

var socket = io.connect('/chat');

雖然連接到指定的房間,但是我們也可以在服務端操作,自由的進出房間:

socket.join('chat');//進入chat房間
socket.leave('chat');//離開chat房間

WebSocket 廣播消息

在實時應用中,廣播是一個不可或缺的功能,socket.io提供兩種服務端廣播方式。

第一種廣播方式可以稱之爲'全局廣播',顧名思義,全局廣播就是所有連接到服務器的客戶端都會受到廣播的信息:

socket.broadcast.emit('DATA',data);

但是,在實際應用場景中,我們很多時候並不需要所有用戶都收到廣播信息,有的廣播信息只發送給一部分客戶端,比如某個房間裏面的用戶,那麼可以使用如下方式:

socket.broadcast.to('chat').emit('DATA',data);

中間件

socket.io提供中間件功能,我們可以通過中間件來對請求進行預處理,比如身份驗證:

io.use(function(socket, next){
 if (socket.request.headers.cookie) return next();
 next(new Error('Authentication error'));
});

示例中展示了通過中間件進行身份驗證,當沒有cookie的時候拋出異常。

傳遞參數

在很多應用場景中,客戶端發起連接請求時都需要傳遞參數,這些參數可能是身份驗證、初始化設置等等,那麼socket.io發起連接時如何傳遞參數呢?

var socket = io.connect('/');

由於connect函數發起連接的參數是一個url,你可能會想到把參數拼接到url上,如http://xxxx?xx=xxxx,但是很遺憾這樣是行不通的,我們可以通過這樣的方式來傳遞參數:

var socket = io.connect('/',{ _query:'sid=123456' });

在服務端可以這樣獲取到傳遞的參數:

io.use(function(socket){
   var query = socket.request._query;
   var sid = query.sid; 
});

客戶端傳遞的參數已經被解析成了一個json對象,這個對象就是_query。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章