上一篇文章簡要的介紹了一下http協議,此次再介紹一下WebSocket協議,二者之間有很大的區別,WebSocket協議是 HTML5 開始提供的一種在單個 TCP 鏈接上進行全雙工通信的協議。html
簡單的理解一下什麼是雙工通信協議,以前有講過http協議只能客戶端向服務端發起請求,是單向的應用層協議。而雙工通信協議,不只客戶端能向服務端發起請求,服務端也能夠主動推送信息給客戶端。node
WebSocket 協議在2008年誕生,2011年成爲國際標準。全部瀏覽器都已經支持了。ios
相比於http協議,websoket協議給咱們帶來了極大的方便,舉個例子:git
以前,咱們在作消息通知的時候,須要設置定時器,頻繁的向後臺發起異步ajax請求實現長輪詢,獲取最新的數據,這樣效率很是低,很是浪費資源,由於不停的發起http請求,不停的與服務端創建鏈接,或者http連接始終打開。
而如今有了websocket,就解決了輪詢的問題,websocket只須要創建一次鏈接,就能夠保持長久鏈接,相比輪詢不停的創建鏈接,大大的提高了效率,這樣只要服務端有數據變化,就能夠當即通知前臺了。github
首先HTTP有 1.1 和 1.0 之說,也就是所謂的 keep-alive ,把多個HTTP請求合併爲一個,可是 Websocket 實際上是一個新協議,跟HTTP協議基本沒有關係,只是爲了兼容現有瀏覽器的握手規範而已,也就是說它是HTTP協議上的一種補充,Websocket是借用了HTTP的協議來完成一部分握手。web
websocket有如下特色:ajax
目前websocket對大部分瀏覽器有很好的兼容,但對於IE10如下的瀏覽器沒法兼容。爲了解決兼容性,Socket.IO就出現了。
Socket.IO是一個基於Nodejs的,用於實時通訊的一個軟件包(包括client端和server端),Socket.IO徹底由JavaScript實現。
平時在應用的時候,能夠直接引入socket.io這個庫就能夠了。先後臺都須要引用該庫。express
下面針對nodejs的服務端如何使用舉個例子:跨域
服務端代碼:瀏覽器
const http = require('http'); const fs = require('fs'); const express = require('express'); const io = require('socket.io'); const app = express(); const httpServer = http.createServer(app); app.use('/', express.static(__dirname + '/www')); httpServer.listen(8081); const ioserve = io.listen(httpServer); let users = []; ioserve.on('connection', (socket) => { socket.on('login', (nickname) => { if (users.indexOf(nickname) > -1) { socket.emit('nickExisted'); } else { socket.userIndex = users.length; socket.nickname = nickname; users.push(nickname); socket.emit('loginSuccess'); ioserve.sockets.emit('system', nickname, users.length, 'login'); } }); socket.on('postMsg', function (msg) { socket.broadcast.emit('newMsg', socket.nickname, msg); }); socket.on('img', function (imgData) { socket.broadcast.emit('newImg', socket.nickname, imgData); }) socket.on('disconnect', function () { users.splice(socket.userIndex, 1); socket.broadcast.emit('system', socket.nickname, users.length, 'logout'); }); })
前臺代碼
html文件
<body> <div class="wrapper"> <div class="banner"> <h1>HiChat :)</h1> <span id="status"></span> </div> <div id="historyMsg"> </div> <div class="controls"> <div class="items"> <input id="colorStyle" type="color" placeHolder='#000' title="font color" /> <input id="emoji" type="button" value="emoji" title="emoji" /> <label for="sendImage" class="imageLable"> <input type="button" value="image" /> <input id="sendImage" type="file" value="image" /> </label> <input id="clearBtn" type="button" value="clear" title="clear screen" /> </div> <textarea id="messageInput" placeHolder="enter to send"></textarea> <input id="sendBtn" type="button" value="SEND"> <div id="emojiWrapper"> </div> </div> </div> <div id="loginWrapper"> <p id="info">connecting to server...</p> <div id="nickWrapper"> <input type="text" placeHolder="nickname" id="nicknameInput" /> <input type="button" value="OK" id="loginBtn" /> </div> </div> <script src="/socket.io/socket.io.js"></script> <script src="js/hichat.js"></script> </body>
js文件
; (function () { function Hichart() { this.socket = null; } Hichart.prototype = { init: function () { var that = this; this.socket = io.connect(); this.socket.on('connect', function () { document.getElementById('info').textContent = 'get yourself a nickname :)'; document.getElementById('nickWrapper').style.display = 'block'; document.getElementById('nicknameInput').focus(); that.login(); that.postMsg(); that.uploadImg(); }); this.socket.on('nickExisted', function () { document.getElementById('info').textContent = '!nickname is taken, choose another pls'; }); this.socket.on('loginSuccess', function () { document.title = 'hichat | ' + document.getElementById('nicknameInput').value; document.getElementById('loginWrapper').style.display = 'none';//隱藏遮罩層顯聊天界面 document.getElementById('messageInput').focus();//讓消息輸入框得到焦點 }); this.socket.on('system', function (nickname, userCount, type) { var msg = nickname + (type === 'login' ? ' joined' : ' left'); that.displayNewMsg('system ', msg, 'red'); document.getElementById('status').textContent = userCount + (userCount > 1 ? ' users' : ' user') + ' online'; }); this.socket.on('newMsg', function (nickname, msg) { that.displayNewMsg(nickname, msg); }); this.socket.on('newImg', function (nickname, newImg) { that.displayImage(nickname, newImg); }); }, login: function () { var that = this; document.getElementById('loginBtn').addEventListener('click', function () { var nickname = document.getElementById('nicknameInput').value; if (nickname.trim().length) { that.socket.emit('login', nickname); } else { document.getElementById('nicknameInput').focus(); } }, false) }, displayNewMsg: function (user, msg, color) { var container = document.getElementById('historyMsg'); var msgToDisplay = document.createElement('p'); var data = new Date().toTimeString().substr(0, 8); msgToDisplay.style.color = color || '#000'; msgToDisplay.innerHTML = user + '<span class="timespan">(' + data + '): </span>' + msg; container.appendChild(msgToDisplay); container.scrollTop = container.scrollHeight; }, displayImage: function (user, imgData, color) { var container = document.getElementById('historyMsg'), msgToDisplay = document.createElement('p'), date = new Date().toTimeString().substr(0, 8); msgToDisplay.style.color = color || '#000'; msgToDisplay.innerHTML = user + '<span class="timespan">(' + date + '): </span> <br/>' + '<a href="' + imgData + '" target="_blank"><img src="' + imgData + '"/></a>'; container.appendChild(msgToDisplay); container.scrollTop = container.scrollHeight; }, postMsg: function () { var that = this; var sendBtn = document.getElementById('sendBtn'); var messageInput = document.getElementById('messageInput'); sendBtn.addEventListener('click', function () { var msg = messageInput.value; if (msg.trim().length != 0) { messageInput.value = ''; messageInput.focus(); that.socket.emit('postMsg', msg); that.displayNewMsg('me', msg); } }); }, uploadImg: function () { var that = this; document.getElementById('sendImage').addEventListener('change', function () { if (this.files.length) { var file = this.files[0]; var reader = new FileReader(); if (!reader) { that.displayNewMsg('system', '!your browser doesn\'t support fileReader', 'red'); this.value = ''; return; } reader.onload = function (e) { this.value = ''; that.socket.emit('img', e.target.result); that.displayImage('me', e.target.result); } reader.readAsDataURL(file); } }) } } window.onload = function () { var hichart = new Hichart(); hichart.init(); } })()
完整demo請查看個人github,地址:https://github.com/jianwenjua...