前言

Socket.IO 是一個用來實現(xiàn)實時雙向通信的框架,其本質(zhì)是基于 WebSocket 技術(shù)。

我們首先來聊聊 WebSocket 技術(shù),先設(shè)想這么一個場景:

· 用戶小A,打開了某個網(wǎng)站的充值界面,該界面上有一個付款的二維碼。

· 當(dāng)小A 用某寶的 APP 掃碼付款之后,網(wǎng)頁要自動跳轉(zhuǎn)到付款成功的界面。最簡單的方法就是網(wǎng)頁每隔一段時間就請求一次服務(wù)器——“怎么樣?那貨付款沒有?”,“怎么樣?還沒付嗎?”,“怎么樣?這次總該付了吧”。

· 當(dāng)接收到服務(wù)端返回確認(rèn)付款的標(biāo)識后,頁面再進行跳轉(zhuǎn)。

這種定時對服務(wù)端發(fā)送 HTTP 請求的技術(shù)也被稱為“輪詢”。輪詢的缺點也顯而易見,短時間內(nèi)的多次訪問無疑會對服務(wù)器造成很大壓力。

  后來,人們發(fā)明了長輪詢技術(shù)。這與短輪詢的區(qū)別在于,每次瀏覽器請求服務(wù)器后,服務(wù)器并不會立即返回“用戶還未付款”的結(jié)果,而是一直將 HTTP 保持在掛起狀態(tài),只有當(dāng)用戶付款后才會返回給瀏覽器 “用戶已經(jīng)付款” 的結(jié)果。當(dāng)然,如果用戶在規(guī)定時間內(nèi)仍未付款還是會斷開此次連接,之后瀏覽器再開始發(fā)送下一輪的長連接。相比短輪詢,長輪詢有了一定的優(yōu)勢,但這還是不夠好。直到 HTML5 里 WebSocket 技術(shù)的誕生。

  WebSocket,即 Web 瀏覽器與 Web 服務(wù)器之間的全雙工通信標(biāo)準(zhǔn)。最初 WebSocket 只是作為 HTML5 標(biāo)準(zhǔn)的一部分,而后來卻逐漸變成了獨立的協(xié)議標(biāo)準(zhǔn)。一旦瀏覽器與服務(wù)器建立起 WebSocket 協(xié)議的通信連接,之后所有的通信都依靠該協(xié)議進行。不論是服務(wù)器還是瀏覽器,任何一方都能向?qū)Ψ桨l(fā)送報文。通信過程中可相互發(fā)送 JSON、HTML或圖片等任意格式的數(shù)據(jù)。

   關(guān)于 WebSocket 的原生 API 如何使用,本文不贅述了。 這里主要聊聊關(guān)于 Socket.IO 這個庫的使用方式。Socket.IO 與 ws 等其他基于 WebSocket 通信的庫相比,它的好處在于,當(dāng)瀏覽器支持 WebSocket 技術(shù)時它能正常使用 WebSocket 來工作,當(dāng)瀏覽器不支持 WebSocket 時,它能平穩(wěn)退化成輪詢進行工作。

 

首先放出自己做的聊天室 DEMO 源碼,將源碼克隆到本地,執(zhí)行下面兩個命令:

npm install
npm start

 接著用瀏覽器訪問 localhost:8000 即可,實際界面如下圖:

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)     平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 

Socket.IO 在客戶端與服務(wù)端二者均有一套 API,我們舉幾個常用的進行說明。

服務(wù)端

new Server

因為 WebSocket 協(xié)議是建立在 HTTP 協(xié)議之上的,所以在創(chuàng)建 WebSocket 服務(wù)時需要調(diào)用 http 模塊并調(diào)用其下的 createServer 方法,將生成的 server 作為參數(shù)傳入 socket.io 的方法中。

var server = require('http').createServer(),
    io = require('socket.io')(server);

server.listen(8000);

 

io.onconnection(socket)

io 的 connection 事件表示客戶端與服務(wù)器成功建立連接,它會接收一個回調(diào)函數(shù),該回調(diào)函數(shù)會接收一個 socket 參數(shù)。

io.on('connection', (socket) => {
    console.log(socket);
});

 

io.emit(EventName, param1, param2...)

io.emit 方法用于向服務(wù)器發(fā)送消息,其第一個參數(shù)表示自定義的數(shù)據(jù)名,后面表示需要配合事件傳入的參數(shù)。

io.on('connection', (socket) => {
    io.emit('server message', {msg: 'Hello World.'})
});

 

socket.on(EventName, callback)

socket.on 方法用于接收客戶端發(fā)送來的消息,EventName 參數(shù)為客戶端自定義的事件名,callback 為回調(diào)函數(shù),回調(diào)函數(shù)接收的參數(shù)即客戶端傳遞來的參數(shù)。

io.on('connection', (socket) => {
    socket.on('client message', (data) => {
        console.log(data);
    });
});

 

socket.broadcast.emit() 

socket.broadcast.emit() 方法表示向除了自己以外的客戶端發(fā)送消息。舉個例子,當(dāng)我們輸入 “Message” 點擊發(fā)送,只需要將 “Message” 通過服務(wù)器發(fā)送給其他客戶端用于顯示,而本地只需要將 “Message” 通過 js 代碼添加進聊天窗口即可,而不需要經(jīng)過服務(wù)器。

io.on('connection', (socket) => {
    socket.broadcast.emit('server message', {
        msg: 'Hello World.'
    });
});

 

socket.ondisconnect

socket 的 disconnect 事件表示客戶端與服務(wù)端斷開連接。

io.on('connection', (socket) => {
    socket.on('disconnect', () => {
        console.log('連接已斷開...');
    });
});

 

客戶端

首先需要引入 socket.io 模塊中的 socket.io.js 文件。

<!Doctype HTML>
<html>
<head>
    <title>Socket.IO chat</title>
    <script src="/socket.io/socket.io.js"></script>
</head>
</html>

引入成功后,就可能通過 io() 生成客戶端所用的 socket 對象。

var socket = io();

 

socket.emit(EventName, param1, param2, .....)

socket.emit 方法用于客戶端向服務(wù)端發(fā)送消息,服務(wù)端與之對應(yīng)的是 socket.on 方法來接收消息。

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

//客戶端var socket = io();
socket.emit('client message', {
    msg: 'Hello Server'});//服務(wù)端io.on('connection', (socket) => {
    socket.on('client message', (data) => {
        console.log(data.msg); // Hello Server    });
});

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 

socket.on(EventName)

socket.on 方法用于接收服務(wù)端發(fā)來的消息

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

//服務(wù)端io.on('connection', (socket) => {
    io.emit('server message', {
        msg: 'Hello Client'
    });
});//客戶端var socket = io();
socket.on('server message', (data) => {
    console.log(data.msg); // Hello Client});

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 

介紹完 Socket.IO 的 API,下面開始嘗試寫聊天室的 DEMO。

首先創(chuàng)建目錄如下:

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

其中 server.js 中保存著服務(wù)端的代碼,client 文件夾中保存著客戶端代碼,包括 HTML、CSS、JS、圖片等。

編寫 server.js 如下:

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

 express = require('express'== require('http'= require('socket.io'= process.env.PORT || 8000+ '/client''connection', (socket) =>= '游客' + socket.id.substring(0, 6
    io.local.emit('user conncet', user + '進入聊天室'
    socket.on('client message', (data) =>=
        socket.broadcast.emit('server message'
    socket.on('disconnect', () =>
        io.local.emit('user disconnect', user + '離開聊天室'=>'listening on %d...'

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

前端部分代碼省略,這里只簡單寫一個發(fā)送消息的方法,具體的代碼請參考 DEMO 源碼

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

var socket = io();function sendMsg() {    var message = document.querySelector('#input');
    
    socket.emit('client message', {
        text: message,
        time: new Date()
    });

    document.querySelector('#content').innerHTML += '<div class="msgList">'+message+'</div>';}

平面設(shè)計培訓(xùn),網(wǎng)頁設(shè)計培訓(xùn),美工培訓(xùn),游戲開發(fā),動畫培訓(xùn)

如上,當(dāng)運行 server.js 文件后,在瀏覽器地址欄中輸入 localhost:8000 就可以看到聊天室的界面了。 這樣我們就完成了一個簡易的聊天室,它包括如下功能:

· 發(fā)送/接收消息

· 通知用戶進入/離開

· 為進入聊天室的用戶命名,名稱唯一

有興趣的朋友還可以嘗試自行完成如下功能:

· 用戶登陸

· 查看所有在線用戶

http://www.cnblogs.com/ghost-xyx/p/7060070.html