本博之前有过几篇长链接的博文,算了,原生的php socket扩展我放弃了,也用php的swoole扩展实现过websocket聊天室,不过,还是用node.js的socket.io库方便。一开始,尝试不用库,直接写node,不过发现我并没有什么耐心去研究websocket协议,还是用socket.io方便,屏蔽了底层,只关注逻辑。
聊天室地址:http://chat.feehi.com
github地址:http://github.com/liufee/chat
写了一段时间的node.js了,真的很有意思,我很喜欢node。不过,我感觉node也有很多不完善的地方,比如说this.key=value,这个key不可以是变量!!!基于对象并非面向对象,好尴尬~~~还有,那个前套n+1层的异步,还是协程好。。。
用了socket.io库之后,整个后端的代码量其实很少,server.js:
var io = require("socket.io")(5000); var mongodb = require('mongodb'); var server = new mongodb.Server('localhost', 27017, {auto_reconnect:true}); var db = new mongodb.Db('feehi', server, {safe:true}); var collection; //连接db db.open(function(err, db){ if(err) console.log(err); console.log('connect mongodb success'); // 第1种连接方式 db.collection('chat',{safe:true}, function(err, collect){ if(err){ console.log(err); } collection = collect; }); }) //db.createCollection('mycoll', {safe:true}, function(err, collection){})第二种连接 var onlineUsers = {};//在线用户 var onlineCount = 0;//在线用户人数 var userSockets = {}; io.on('connection', function(socket){ console.log("a user connected"); socket.on('login', function(data){ if(!onlineUsers.hasOwnProperty(data.username)){ socket.name = data.username; onlineUsers[data.username] = data; userSockets[data.username] = socket; onlineCount++; } collection.find().sort({_id:-1}).limit(15).toArray(function(err,chatList){ if(err) console.log(err); socket.emit('initChat', {chatList:chatList}); }); io.emit('login', {onlineUsers:onlineUsers, onlineCount:onlineCount, user:data}); console.log(data.username+'加入了聊天室'); }); socket.on('message', function(data){ var dt = new Date(); var time = (dt.getFullYear())+'-'+(parseInt(dt.getMonth())+1)+'-'+(dt.getDate())+' '+(dt.getHours())+':'+(dt.getMinutes())+':'+(dt.getSeconds()); data.time = time; var dt = {username:data.username,content:data.content,time:data.time}; io.emit('message', dt); collection.insert(dt, {safe:true},function(err, result){ //console.log(result); }); console.log(dt.username+'说: '+dt.content); }); socket.on('disconnect', function(){ if(onlineUsers.hasOwnProperty(socket.name)){ var logoutUser = socket.name; console.log(socket.name+'退出了聊天室'); delete onlineUsers[socket.name]; delete userSockets[socket.name]; onlineCount--; io.emit('logout', {logoutUser:logoutUser,onlineCount:onlineCount}); } }) socket.on('privateChat', function(data){ var dt = new Date(); var time = (dt.getFullYear())+'-'+(parseInt(dt.getMonth())+1)+'-'+(dt.getDate())+' '+(dt.getHours())+':'+(dt.getMinutes())+':'+(dt.getSeconds()); data.time = time; userSockets[data.toWhom].emit('privateChat', data); userSockets[data.username].emit('privateChat', data); console.log(data.username+"对"+data.toWhom+"说 "+data.content); }) });
因为之前的nosql一直用的redis,所以,这次保存公共聊天记录用的是mongodb,mongodb果真是流弊闪闪,真的能替代mysql吗,哈哈,mongodb的学习成本还是蛮低的,首先想起标准的sql语句该怎么写,然后转换成mongodb的语法…
socket.io已经封装的太好了,只要掌握on是接收,emit是发送,双向通信,就可以了,主要复杂的还是前端的逻辑,还好,我前端用jquery库来操作dom。
转载请注明:飞嗨 » node.js聊天室