一般咱們web使用的是http協議,可是 HTTP 協議有一個缺陷:通訊只能由客戶端發起。html
因此咱們須要一個能夠由服務端主動發出的協議,即WebSocket。node
WebSocket是HTML5新增的一種通訊協議,其特色是服務端能夠主動向客戶端推送信息,客戶端也能夠主動向服務端發送信息,是真正的雙向平等對話,屬於服務器推送技術的一種。jquery
Socket.IO 是一個基於 Node.js 的實時應用程序框架,在即時通信、通知與消息推送,實時分析等場景中有較爲普遍的應用。web
socket.io 包含兩個部分:express
固然,socket.IO構架在一個nodejs服務上,這裏開啓一個express服務。npm
建立文件夾socketIODemo,而後安裝瀏覽器
npm init -y
npm install express --save
以後在socketIODemo中建立文件index.js:服務器
const express = require('express') const app = express() app.use(express.static(__dirname + '/public')); app.listen(3000, () => console.log('Example app listening on port 3000!'))
建立靜態資源public/index.html :app
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> * { margin: 0; padding: 0; } html, body { height: 100%; overflow: hidden; } .chat { float: left; padding: 1em 1em 0 2em; height: 100%; width: 500px; border-right: 1px solid #DA4; overflow-y: scroll; } .inputpart { float: left; margin-left: 10px; } #userName { font-size: 20px; color: rgb(3, 57, 109); } </style> </head> <body> <div class="chat"> <ul id="messages"> //聊天信息 </ul> </div> <div class="inputpart"> <div id="userName"> //用來展現用戶id </div> <form action=""> <input autocomplete="off" id="inpB" /><button id="say">Send</button> </form> </div> </body> </html>
此時開啓服務: node index, 訪問localhost:3000。框架
服務開啓!
安裝:
npm install socket.io --save
而後在index.js中註冊socket.io,並改成http監聽:
let http = require('http').Server(app) const io = require('socket.io')(http) app.use(express.static(__dirname + '/public')); http.listen(3000, () => console.log('Example app listening on port 3000!'))
此時服務已改成WebSocket服務。
服務端運行後會在根目錄動態生成socket.io的客戶端js文件,客戶端能夠經過固定路徑/socket.io/socket.io.js添加引用。
在HTML中引用js文件,並調用:
<script src="/socket.io/socket.io.js"></script> <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> <script> $(function () { var userName = ''; while ($('#userName').text().trim() === '') { //設置用戶名 let promptName = prompt("請設置你的暱稱", "") userName = promptName ? promptName + ':' : '未命名:'; $('#userName').text(userName); } let socket = io(); socket.on('connect', function () { socket.emit('join', userName) }) // 監聽系統消息 socket.on('sys', function (sysMsg) { var message = '<div class="sysMsg">' + sysMsg + '</div>'; $('#messages').append(message); }); }) </script>
這段代碼中,socket.on('connect', function () { })
爲默認監聽事件,socket.io 提供了默認事件(如:connect, message, disconnect)。也能夠自定義。socket.emit('action');
表示發送了一個action命令,命令是字符串的。
後臺index.js文件中:
io.on('connection', function (socket) { console.log('a user connected') let userID = '' socket.on('join', function (userName) { userID = userName; io.emit('sys', userID + '已加入房間'); console.log(userID + '加入了'); }); })
connection事件在客戶端成功鏈接到服務端時觸發,有了這個事件,咱們能夠隨時掌握用戶鏈接到服務端的信息。
當客戶端成功創建鏈接時,在connection事件的回調函數中,咱們仍是能夠爲socket註冊一些經常使用的事件,如:disconnect事件socket.on('disconnect',function(){...});
,它在客戶端鏈接斷開是觸發,這時候我就知道用戶已經離開了。
重啓服務,打開多個窗口,查看聊天框內容:
下面添加聊天功能。
在HTML文件中添加事件監聽click:
$('#say').click((e) => { e.preventDefault() socket.send($("#inpB")[0].value) $("#inpB")[0].value = '' }) socket.on('msg', function (userName, userColor, msg) { var message = ' <div class="message">' + `<span class="user" style="font-size:1.5em; color: #${userColor}">` + userName + '</span>' + ' <span class="msg">' + msg + '</span>' + '</div>'; $('#messages').append(message); // 滾動條保持最下方 $('#messages').scrollTop($('#messages')[0].scrollHeight); });
這段代碼中,首先監聽事件並將input中內容send回去;socket.on爲自定義事件msg
用來接收後臺發送來的其餘人的發言。
socket.emit和socket.send的區別在stackoverflow中有一個解釋大意是說emit能夠自定義事件,而send不能夠,且只能以message接收。
後臺index.js:
io.on('connection', function (socket) { console.log('a user connected') let userID = '', userColor =parseInt(Math.random() * 16777216).toString(16) socket.on('join', function (userName) { userID = userName; io.emit('sys', userID + '已加入房間'); console.log(userID + '加入了'); }); socket.on('message', function (msg){ io.emit('msg', userID, userColor, msg) }) })
爲新的成員隨機匹配顏色,並將message監聽到的信息經過自定義爲msg
的事件emit出去。
此時,一個簡易聊天室已經完成。
讀者能夠自行添加退出功能,或者設置多個房間。。。