1 client: socket.io
server: node.js + express + socket.io
一個簡單的聊天室 demo,沒有注冊,內置了一些測試用戶
2 client 關鍵代碼
var socket = io.connect('http://localhost:8080'); socket.on('connect',function(){ console.log('connected to server'); socket.on('login success',function(data){ console.log('login success'); username = data.username; refreshOnlineUsers(data.allusers); }); socket.on('disconnect',function(){ console.log('disconnect'); username = null; }); socket.on('login failed',function(){ username = null; }); socket.on('new message',function(data){ console.log('receiver message from '+data.fromUser +' '+data.date+ ' '+data.msg); }); socket.on('update myself',function(data){ }); socket.on('enter chat',function(data){ console.log(data.username+' has entered the chat'); refreshOnlineUsers(data.allusers); }); socket.on('leave chat',function(data){ console.log(data.username + ' has leaved the chat'); refreshOnlineUsers(data.allusers); }); });
3 server 關鍵代碼
var express = require('express'); var app = express(); var server = require('http').Server(app); var io = require('socket.io')(server); app.use('/', express.static(__dirname + '/www')); var users = { fanglin:{ socket:null, online:false }, xingtianyu:{ socket:null, online:false } }; io.on('connection', function(socket){ socket.on('new message',function(data){ var i,user; socket.emit('update myself',{fromUser:data.fromUser,msg:data.msg,date:new Date()}); if(data.broadcast===true){ socket.broadcast.emit('new message',{fromUser:data.fromUser,msg:data.msg,date:new Date()}); }else{ for(i=0;i<data.tousers.length;i++){ user = users[data.tousers[i]]; if(user.online==true && user.socket!=null){ user.socket.emit('new message',{fromUser:data.fromUser,msg:data.msg,date:new Date()}); } } } }); socket.on('login',function(data){ if(data.username in users){ users[data.username].online = true; users[data.username].socket = socket; socket.emit('login success',{username:data.username,allusers:getOnlineUsers()}); socket.broadcast.emit('enter chat',{username:data.username,allusers:getOnlineUsers()}); }else{ socket.emit('login failed'); } }); socket.on('disconnect',function(){ var user; for (user in users){ if(users[user].socket == socket){ users[user].online = false; socket.broadcast.emit('leave chat',{username:user,allusers:getOnlineUsers()}); return; } } }); }); server.listen(8080); console.log('server is listenering on port 8080');
4 實現了一個簡單的有限狀態機
(1) 客戶端啟動時去連接服務器,連接成功觸發服務端的 connection 事件
(2) 連接成功后客戶端可登陸,觸發服務端的 login 事件,服務端查找用戶,若登陸成功服務端向客戶端發送 login success 的消息,並返回所有在線用戶,同時向其他在線用戶發送 enter chat 廣播,登陸失敗則向客戶端發送 login failed 消息。
(3) 客戶端登陸成功后可向其他在線用戶發送消息,客戶端向服務端發送 new message 消息,服務端收到 new message 消息后,先向客戶端發送 update myself 消息,客戶端如果勾選了 Select All, 服務端會接着發送 new message 廣播,否則遍歷所有接收者,依次向這些接收者發送 new message 消息。
(4) 客戶端斷開連接后觸發服務端 disconnect 事件,服務端發送 leave chat 廣播。
(5) 客戶端在收到 new message update myself 時會更新聊天室里的聊天內容。收到 login success 、 enter chat 、leave chat 時會更新當前在線用戶。收到 login success 、login failed 時更新在線狀態 。。。
代碼不多非常簡單,大家一看就能明白.
代碼地址: https://github.com/lesliebeijing/MyChatRoom.git