前言html
Socket.IO 是一個用來實現實時雙向通訊的框架,其本質是基於 WebSocket 技術。前端
咱們首先來聊聊 WebSocket 技術,先設想這麼一個場景:git
· 用戶小A,打開了某個網站的充值界面,該界面上有一個付款的二維碼。github
· 當小A 用某寶的 APP 掃碼付款以後,網頁要自動跳轉到付款成功的界面。最簡單的方法就是網頁每隔一段時間就請求一次服務器——「怎麼樣?那貨付款沒有?」,「怎麼樣?還沒付嗎?」,「怎麼樣?此次總該付了吧」。web
· 當接收到服務端返回確認付款的標識後,頁面再進行跳轉。express
這種定時對服務端發送 HTTP 請求的技術也被稱爲「輪詢」。輪詢的缺點也顯而易見,短期內的屢次訪問無疑會對服務器形成很大壓力。npm
後來,人們發明了長輪詢技術。這與短輪詢的區別在於,每次瀏覽器請求服務器後,服務器並不會當即返回「用戶還未付款」的結果,而是一直將 HTTP 保持在掛起狀態,只有當用戶付款後纔會返回給瀏覽器 「用戶已經付款」 的結果。固然,若是用戶在規定時間內仍未付款仍是會斷開這次鏈接,以後瀏覽器再開始發送下一輪的長鏈接。相比短輪詢,長輪詢有了必定的優點,但這仍是不夠好。直到 HTML5 裏 WebSocket 技術的誕生。瀏覽器
WebSocket,即 Web 瀏覽器與 Web 服務器之間的全雙工通訊標準。最初 WebSocket 只是做爲 HTML5 標準的一部分,然後來卻逐漸變成了獨立的協議標準。一旦瀏覽器與服務器創建起 WebSocket 協議的通訊鏈接,以後全部的通訊都依靠該協議進行。不管是服務器仍是瀏覽器,任何一方都能向對方發送報文。通訊過程當中可相互發送 JSON、HTML或圖片等任意格式的數據。服務器
關於 WebSocket 的原生 API 如何使用,本文不贅述了。 這裏主要聊聊關於 Socket.IO 這個庫的使用方式。Socket.IO 與 ws 等其餘基於 WebSocket 通訊的庫相比,它的好處在於,當瀏覽器支持 WebSocket 技術時它能正常使用 WebSocket 來工做,當瀏覽器不支持 WebSocket 時,它能平穩退化成輪詢進行工做。websocket
首先放出本身作的聊天室 DEMO 源碼,將源碼克隆到本地,執行下面兩個命令:
npm install
npm start
接着用瀏覽器訪問 localhost:8000 便可,實際界面以下圖:
Socket.IO 在客戶端與服務端兩者均有一套 API,咱們舉幾個經常使用的進行說明。
服務端
new Server
由於 WebSocket 協議是創建在 HTTP 協議之上的,因此在建立 WebSocket 服務時須要調用 http 模塊並調用其下的 createServer 方法,將生成的 server 做爲參數傳入 socket.io 的方法中。
var server = require('http').createServer(), io = require('socket.io')(server); server.listen(8000);
io.onconnection(socket)
io 的 connection 事件表示客戶端與服務器成功創建鏈接,它會接收一個回調函數,該回調函數會接收一個 socket 參數。
io.on('connection', (socket) => {
console.log(socket);
});
io.emit(EventName, param1, param2...)
io.emit 方法用於向服務器發送消息,其第一個參數表示自定義的數據名,後面表示須要配合事件傳入的參數。
io.on('connection', (socket) => { io.emit('server message', {msg: 'Hello World.'}) });
socket.on(EventName, callback)
socket.on 方法用於接收客戶端發送來的消息,EventName 參數爲客戶端自定義的事件名,callback 爲回調函數,回調函數接收的參數即客戶端傳遞來的參數。
io.on('connection', (socket) => { socket.on('client message', (data) => { console.log(data); }); });
socket.broadcast.emit()
socket.broadcast.emit() 方法表示向除了本身之外的客戶端發送消息。舉個例子,當咱們輸入 「Message」 點擊發送,只須要將 「Message」 經過服務器發送給其餘客戶端用於顯示,而本地只須要將 「Message」 經過 js 代碼添加進聊天窗口便可,而不須要通過服務器。
io.on('connection', (socket) => { socket.broadcast.emit('server message', { msg: 'Hello World.' }); });
socket.ondisconnect
socket 的 disconnect 事件表示客戶端與服務端斷開鏈接。
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 方法用於客戶端向服務端發送消息,服務端與之對應的是 socket.on 方法來接收消息。
//客戶端 var socket = io(); socket.emit('client message', { msg: 'Hello Server' }); //服務端 io.on('connection', (socket) => { socket.on('client message', (data) => { console.log(data.msg); // Hello Server }); });
socket.on(EventName)
socket.on 方法用於接收服務端發來的消息
//服務端 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 });
介紹完 Socket.IO 的 API,下面開始嘗試寫聊天室的 DEMO。
首先建立目錄以下:
其中 server.js 中保存着服務端的代碼,client 文件夾中保存着客戶端代碼,包括 HTML、CSS、JS、圖片等。
編寫 server.js 以下:
var express = require('express'), app = express(), server = require('http').createServer(app), io = require('socket.io')(server), port = process.env.PORT || 8000;
//經過 express 加載前端部分的靜態資源文件 app.use(express.static(__dirname + '/client')); io.on('connection', (socket) => {
//經過 socket.id 建立簡易的用戶名 let user = '遊客' + socket.id.substring(0, 6); //通知用戶進入 io.local.emit('user conncet', user + '進入聊天室'); //接收從客戶端發送來的消息,拼上消息發佈者的名字後,廣播給其餘客戶端 socket.on('client message', (data) => { data.author = user; //將消息廣播給除本身之外的客戶端 socket.broadcast.emit('server message', data); }); //通知用戶離開 socket.on('disconnect', () => { io.local.emit('user disconnect', user + '離開聊天室'); }); }); server.listen(port, () => { console.log('listening on %d...', port); });
前端部分代碼省略,這裏只簡單寫一個發送消息的方法,具體的代碼請參考 DEMO 源碼。
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>'; }
如上,當運行 server.js 文件後,在瀏覽器地址欄中輸入 localhost:8000 就能夠看到聊天室的界面了。 這樣咱們就完成了一個簡易的聊天室,它包括以下功能:
· 發送/接收消息
· 通知用戶進入/離開
· 爲進入聊天室的用戶命名,名稱惟一
有興趣的朋友還能夠嘗試自行完成以下功能:
· 用戶登錄
· 查看全部在線用戶
· @ 功能
···
感受你的瀏覽,但願能有所幫助。