socket.io簡介
在Html5中存在著這樣的一個新特性,引入了websocket,關于websocket的內部實現原理可以看這篇文章,這篇文章講述了websocket無到有,根據協議,分析數據幀的頭,進行構建websocket。雖然代碼短,但可以很好地體現websocket的原理。
,這個特性提供了瀏覽器端和服務器端的基于TCP連接的雙向通道。但是并不是所有的瀏覽器都支持websocket特性,故為了磨平瀏覽器間的差異,為開發者提供統一的接口,引入了socket.io模塊。在不支持websoket的瀏覽器中,socket.io可以降級為其他的通信方式,比如有AJAX long polling ,JSONP Polling等。
模塊安裝
新建一個package.json文件,在文件中寫入如下內容:
{ "name": "socketiochatroom", "version": "0.0.1", "dependencies": { "socket.io": "*", "express":"*" } }
npm install
執行完這句,node將會從npm處下載socket.io和express模塊。
-
服務器端的實現
在文件夾中添加index.js文件,并在文件中寫入如下內容:
/** * Created by bamboo on 2016/3/31. */ var app = require('express')(); var http = require('http').Server(app); var io = require('socket.io')(http); app.get('/', function (req, res) { "use strict"; res.end("<h2>socket server</h2>") }); /*在線人員*/ var onLineUsers = {}; /* 在線人數*/ var onLineCounts = 0; /*io監聽到存在鏈接,此時回調一個socket進行socket監聽*/ io.on('connection', function (socket) { console.log('a user connected'); /*監聽新用戶加入*/ socket.on('login', function (user) { "use strict"; //暫存socket.name 為user.userId;在用戶退出時候將會用到 socket.name = user.userId; /*不存在則加入 */ if (!onLineUsers.hasOwnProperty(user.userId)) { //不存在則加入 onLineUsers[user.userId] = user.userName; onLineCounts++; } /*一個用戶新加入,向所有客戶端監聽login的socket的實例發送響應,響應內容為一個對象*/ io.emit('login', {onLineUsers: onLineUsers, onLineCounts: onLineCounts, user: user}); console.log(user.userName, "加入了聊天室");//在服務器控制臺中打印么么么用戶加入到了聊天室 }); /*監聽用戶退出聊天室*/ socket.on('disconnect', function () { "use strict"; if (onLineUsers.hasOwnProperty(socket.name)) { var user = {userId: socket.name, userName: onLineUsers[socket.name]}; delete onLineUsers[socket.name]; onLineCounts--; /*向所有客戶端廣播該用戶退出群聊*/ io.emit('logout', {onLineUsers: onLineUsers, onLineCounts: onLineCounts, user: user}); console.log(user.userName, "退出群聊"); } }) /*監聽到用戶發送了消息,就使用io廣播信息,信息被所有客戶端接收并顯示。注意,如果客戶端自己發送的也會接收到這個消息,故在客戶端應當存在這的判斷,是否收到的消息是自己發送的,故在emit時,應該將用戶的id和信息封裝成一個對象進行廣播*/ socket.on('message', function (obj) { "use strict"; /*監聽到有用戶發消息,將該消息廣播給所有客戶端*/ io.emit('message', obj); console.log(obj.userName, "說了:", obj.content); }); }); /*監聽3000*/ http.listen(3000, function () { "use strict"; console.log('listening 3000'); });
運行服務器端程序
node index.js
輸出
listening 3000
此時在瀏覽器中打開localhost:3000會得到這樣的結果:
原因是在代碼中只對路由進行了如下設置
app.get('/', function (req, res) { "use strict"; res.end("<h2>socket server</h2>") });
服務器端主要是提供socketio服務,并沒有設置路由。
客戶端的實現
在客戶端建立如下的目錄和文件,其中json3.min.js可以從網上下載到。
client
- - - client.js
- - - index.html
- - - json3.min.js
- - - style.css
在index.html中
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="format-detection" content="telephone=no"/> <meta name="format-detection" content="email=no"/> <title>1301群聊</title> <link rel="stylesheet" type="text/css" href="./style.css"/> <script src="http://realtime.plhwin.com:3000/socket.io/socket.io.js"></script> <script src="./json3.min.js"></script> </head> <body> <div id="loginbox"> <div > 輸入你在群聊中的昵稱 <br/> <br/> <input type="text" placeholder="請輸入用戶名" id="userName" name="userName"/> <input type="button" value="提交" onclick="CHAT.userNameSubmit();"/> </div> </div> <div id="chatbox" > <div > <div > <span >1301群聊</span> <span ><span id="showUserName"></span>| <a href="javascript:;" onclick="CHAT.logout()" >退出</a></span> </div> </div> <div id="doc"> <div id="chat"> <div id="message" class="message"> <div id="onLineCounts" > </div> </div> <div class="input-box"> <div class="input"> <input type="text" maxlength="140" placeholder="輸入聊天內容 " id="content" name="content" > </div> <div class="action"> <button type="button" id="mjr_send" onclick="CHAT.submit();">提交</button> </div> </div> </div> </div> </div> <script type="text/javascript" src="./client.js"></script> </body> </html>
在client.js中
/** * Created by bamboo on 2016/3/31. */ /*即時運行函數*/ (function () { "use strict"; var d = document, w = window, dd = d.documentElement, db = d.body, dc = d.compatMode === "CSS1Compat", dx = dc ? dd : db, ec = encodeURIComponent, p = parseInt; w.CHAT = { msgObj: d.getElementById("message"), screenHeight: w.innerHeight ? w.innerHeight : dx.innerHeight, userName: null, userId: null, socket: null, /*滾動條始終在最底部*/ scrollToBottom: function () { w.scrollTo(0, this.msgObj.clientHeight); }, /*此處僅為簡單的刷新頁面,當然可以做復雜點*/ logout: function () { // this.socket.disconnect(); w.top.location.reload(); }, submit: function () { var content = d.getElementById('content').value; if (content != '') { var obj = { userId: this.userId, userName: this.userName, content: content }; //如在服務器端代碼所說,此對象就行想要發送的信息和發送人組合成為對象一起發送。 this.socket.emit('message', obj); d.getElementById('content').value = ''; } return false; }, /**客戶端根據時間和隨機數生成ID,聊天用戶名稱可以重復*/ genUid: function () { return new Date().getTime() + "" + Math.floor(Math.random() * 889 + 100); }, /*更新系統信息 主要是在客戶端顯示當前在線人數,在線人列表等,當有新用戶加入或者舊用戶退出群聊的時候做出頁面提示。*/ updateSysMsg: function (o, action) { var onLineUsers = o.onLineUsers; var onLineCounts = o.onLineCounts; var user = o.user; //更新在線人數 var userHtml = ''; var separator = ''; for (var key in onLineUsers) { if (onLineUsers.hasOwnProperty(key)) { userHtml += separator + onLineUsers[key]; separator = '、'; } } //插入在線人數和在線列表 d.getElementById('onLineCounts').innerHTML = '當前共有' + onLineCounts + "在線列表: " + userHtml; //添加系統消息 var html = ''; html += '<div class="msg_system">'; html += user.userName; html += (action === "login") ? "加入了群聊" : "退出了群聊"; html += '</div>'; var section = d.createElement('section'); section.className = 'system J-mjrlinkWrap J-cutMsg'; section.innerHTML = html; this.msgObj.appendChild(section); this.scrollToBottom(); }, /*用戶提交用戶名后,將loginbox設置為不顯示,將chatbox設置為顯示*/ userNameSubmit: function () { var userName = d.getElementById('userName').value; if (userName != '') { d.getElementById('userName').value = ''; d.getElementById('loginbox').style.display = 'none'; d.getElementById('chatbox').style.display = 'block'; this.init(userName);//調用init方法 } return false; }, //用戶初始化 init: function (userName) { //隨機數生成uid this.userId = this.genUid(); this.userName = userName; d.getElementById('showUserName').innerHTML = this.userName;//[newpidian]|[退出] this.scrollToBottom(); //連接socketIO服務器,newpidian的IP地址 this.socket = io.connect('192.168.3.155:3000'); //向服務器發送某用戶已經登錄了 this.socket.emit('login', {userId: this.userId, userName: this.userName}); //監聽來自服務器的login,即在客戶端socket.emit('login ')發送后,客戶端就會收到來自服務器的 // io.emit('login', {onLineUsers: onLineUsers, onLineCounts: onLineCounts, user: user}); /*監聽到有用戶login了,更新信息*/ this.socket.on('login', function (o) { //更新系統信息 CHAT.updateSysMsg(o, 'login'); }); /*監聽到有用戶logout了,更新信息*/ this.socket.on('logout', function (o) { CHAT.updateSysMsg(o, 'logout'); }); //var obj = { // userId: this.userId, // userName: this.userName, // content: content //}; /*監聽到有用戶發送消息了*/ this.socket.on("message", function (obj) { //判斷消息是不是自己發送的 var isMe = (obj.userId === CHAT.userId); var contentDiv = '<div>' + obj.content + '</div>'; var userNameDiv = '<span>' + obj.userName + '</span>'; var section = d.createElement('section'); if (isMe) { section.className = 'user'; section.innerHTML = contentDiv + userNameDiv; } else { section.className = 'service'; section.innerHTML = userNameDiv + contentDiv; } CHAT.msgObj.appendChild(section); CHAT.scrollToBottom(); }); } } /*控制鍵鍵碼值(keyCode) 按鍵 鍵碼 按鍵 鍵碼 按鍵 鍵碼 按鍵 鍵碼 BackSpace 8 Esc 27 Right Arrow 39 -_ 189 Tab 9 Spacebar 32 Dw Arrow 40 .> 190 Clear 12 Page Up 33 Insert 45 /? 191 Enter 13 Page Down 34 Delete 46 `~ 192 Shift 16 End 35 Num Lock 144 [{ 219 Control 17 Home 36 ;: 186 \| 220 Alt 18 Left Arrow 37 =+ 187 ]} 221 Cape Lock 20 Up Arrow 38 ,< 188 '" 222 * */ //通過“回車鍵”提交用戶名 d.getElementById('userName').onkeydown = function (e) { console.log(e); e = e || event; if (e.keyCode === 13) { CHAT.userNameSubmit(); } }; //通過“回車鍵”提交聊天內容 d.getElementById('content').onkeydown = function (e) { e = e || event; if (e.keyCode === 13) { CHAT.submit(); } }; })();
style.css
秘密
運行結果
服務器端已經運行,現將客戶端也運行起來得到下圖:
添加了new和pidian兩個用戶,并發送信息和進行退出,得到下面的結果:
以上所述是小編給大家介紹的基于Nodejs利用socket.io實現多人聊天室,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對億速云網站的支持!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。