週末斷斷續續的寫了第一個socket.io Demo。初次接觸socket.io是從其官網看到的,看着get started作了一遍,根據官網的Demo能提供簡單的服務端和客戶端通信。 這個Demo的過程當中用到最多的就是訂閱事件、觸發事件、廣播事件。javascript
根據官網完成Demo後,看到下面提到了幾個問題,又繼續實現了四個功能,其它幾個還要繼續實現。html
①、當有新用戶登陸或離開時廣播消息。java
②、添加暱稱。我在demo中的作法是把用戶輸入的第一條消息做爲暱稱。node
③、發送消息時本身發送的消息再也不給本身發送,其實也就是隻調用廣播(socket.broadcast.emit)消息的方法便可。jquery
④、顯示當前在線用戶和在線人數。express
node:0.12.7json
express:4.13.7服務器
socket.io:1.3.7app
①、客戶端html頁面<script src="/socket.io/socket.io.js"></script>
這樣引用js代碼沒搞明白,百度搜索了一下,有人解釋說是由於express提供的框架轉化了路徑,因此你這樣作是能夠引用到該js的,剛接觸應該會感到意外,可是我實驗若是你只是引用了express而不是用express建立項目的話可能仍是無論用。框架
②、在體驗Demo而且看其餘人寫的例子中發現,不少狀況下客戶端和服務端觸發的事件名稱都相同,不理解這種狀況他們是同一個事件嗎? 會不會產生衝突呢?
一、系統初始化,當你打開頁面時會提示你鏈接至服務器,你輸入第一條消息就是暱稱。
二、輸入暱稱,以一樣的方式再打開幾個Tab頁,輸入暱稱。
三、兩個客戶端聊天
var express=require('express'); var app=express(); var http=require('http').Server(app); var io=require('socket.io')(http); app.get('/',function(req,res){ res.sendFile(__dirname+'/index.html'); }); var onlineUserCount=0; //客戶端鏈接數量 var onlineUsers={}; //統計客戶端登陸用戶 io.on('connection',function(socket){ socket.emit('open'); //通知客戶端已鏈接 //構造客戶端對象 var client={ socket:socket, name:false } //監聽客戶端的chat message事件, 該事件由客戶端觸發 //當服務端收到消息後,再把該消息播放出去,繼續觸發chat message事件, 而後在客戶端監聽chat message事件。 socket.on('chat message',function(msg){ console.log('chat message:'+msg); var obj={time:getTime()}; //構建客戶端返回的對象 //判斷是否是第一次鏈接,以第一條消息做爲暱稱 if(!client.name){ onlineUserCount++; client.name=msg; obj['text']=client.name; obj['author']='Sys'; obj['type']='welcome'; obj['onlineUserCount']=onlineUserCount; socket.name=client.name; //用戶登陸後設置socket.name, 當退出時用該標識刪除該在線用戶 if(!onlineUsers.hasOwnProperty(client.name)){ onlineUsers[client.name]=client.name; } obj['onlineUsers']=onlineUsers; //當前在線用戶集合 console.log(client.name+' login,當前在線人數:'+onlineUserCount); //返回歡迎語 socket.emit('system',obj); //發送給本身的消息 //廣播新用戶已登陸 socket.broadcast.emit('system',obj); //向其餘用戶發送消息 }else{ //若是不是第一次聊天,則返回正常的聊天消息 obj['text']=msg; obj['author']=client.name; obj['type']='message'; console.log(client.name+' say:'+msg); socket.emit('chat message',obj); //發送給本身的消息 , 若是不想打印本身發送的消息,則註釋掉該句。 socket.broadcast.emit('chat message',obj); //向其餘用戶發送消息 } //io.emit('chat message',msg); }); socket.on('disconnect',function(){ onlineUserCount--; if(onlineUsers.hasOwnProperty(socket.name)){ delete onlineUsers[client.name]; } var obj={ time:getTime(), author:'Sys', text:client.name, type:'disconnect', onlineUserCount:onlineUserCount, onlineUsers:onlineUsers }; //廣播用戶退出 socket.broadcast.emit('system',obj); //用戶登陸和退出都使用system事件播報 console.log(client.name+' disconnect,當前在線人數:'+onlineUserCount); }); }); http.listen(3000,function(){ console.log('server begin...'); }); var getTime=function(){ var date = new Date(); return date.getHours()+":"+date.getMinutes()+":"+date.getSeconds(); } var getColor=function(){ var colors = ['aliceblue','antiquewhite','aqua','aquamarine','pink','red','green', 'orange','blue','blueviolet','brown','burlywood','cadetblue']; return colors[Math.round(Math.random() * 10000 % colors.length)]; }
<!doctype html> <html> <head> <title>Socket.IO chat</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font: 13px Helvetica, Arial; } div { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; } div input { border: 0; padding: 10px; width: 90%; margin-right: .5%; } div button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; } #messages { list-style-type: none; margin: 0; padding: 0; } #messages li { padding: 5px 10px; } #messages li:nth-child(odd) { background: #eee; } p{padding:5px 10px;} </style> </head> <body> <p id="onlineUser">在線人數:0</p> <ul id="messages"></ul> <div action=""> <input id="m" autocomplete="off" /><button>Send</button> </div> <script src="https://cdn.socket.io/socket.io-1.2.0.js"></script> <script src="http://code.jquery.com/jquery-1.11.1.js"></script> <script type="text/javascript"> var myName=false; var socket= io('http://localhost:3000'); socket.on('open',function(){ $('#messages').append($('<li>').text('已鏈接至服務器,請輸入暱稱')); }); //監聽system事件,判斷welcome或者disconnect,打印系統消息 socket.on('system',function(json){ var sep=''; var onlinehtml=''; var onlineUsers=json.onlineUsers; for(key in onlineUsers){ if(onlineUsers.hasOwnProperty(key)){ onlinehtml+=sep+onlineUsers[key]; sep='、'; } } if(json.type==='welcome'){ $('#messages').append($('<li>').text('Sys('+json.time+')welcome '+json.text)); $('#onlineUser').text('在線人數:'+json.onlineUserCount+'。在線列表:'+onlinehtml); }else if(json.type==='disconnect'){ $('#messages').append($('<li>').text('Sys('+json.time+')bye '+json.text+'')); $('#onlineUser').text('在線人數:'+json.onlineUserCount+'。在線列表:'+onlinehtml); } }); //監聽服務端的chat message事件,接受每一條消息 socket.on('chat message',function(json){ $('#messages').append($('<li>').text(json.author+'('+json.time+')'+':'+json.text)); }); $('#m').keydown(function(e){ if(e.keyCode===13){ socket.emit('chat message',$('#m').val()); //socket.send($('#m').val()); $('#m').val(''); if(myName===false){ myName=$('#m').val(); } } }) </script> </body> </html>
作這個Demo的過程當中,感受目前用到最多的就是訂閱事件和發佈事件,而後客戶端和服務端接受相應的參數,另一個就是服務端和客戶端通訊能夠徹底用JSON格式傳參,的確很方便。 目前掌握的方法就是socket.emit()和socket.broadcast.emit(),尚未搞明白emit()和send()的區分。
提供代碼下載地址:http://pan.baidu.com/s/1mgm12Rm