本博之前有过几篇长链接的博文,算了,原生的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聊天室


