Pomelo 0.2
node.js 0.8
由于0.3版本的不稳定,不想花时间到兼容性升级上,等等稍微稳定一下再升级,接下来的分析都是基于这个版本源码进行分析
开篇前,先引用pomelo的wiki:https://github.com/NetEase/pomelo/wiki/tutorial1--%E5%88%86%E5%B8%83%E5%BC%8F%E8%81%8A%E5%A4%A9
本篇属于开篇文章,wiki提到的我就不详细说了,大概流程理顺一下。
客户端:
web-server/public/js/client.js
pomelo.init({ host: host, port: port, log: true }, function() { var route = "connector.entryHandler.enter"; pomelo.request(route, { username: username, rid: rid }, function(data) { if(data.error) { showError(DUPLICATE_ERROR); return; } setName(); setRoom(); showChat(); initUserList(data); }); });
字符串’connector.entryHandler.enter’分别代表了服务器类型、服务端相应的文件名及对应的方法名。根据字符串的标记调用对应的服务器钩子处理。
connector/handler/entryHandler.js
handler.enter = function(msg, session, next) { var self = this; var rid = msg.rid; var uid = msg.username + '*' + rid var sessionService = self.app.get('sessionService'); //duplicate log in if( !! sessionService.getByUid(uid)) { next(null, { code: 500, error: true }); return; } session.bind(uid); session.set('rid', rid); session.push('rid', function(err) { if(err) { console.error('set rid for session service failed! error is : %j', err.stack); } }); session.on('closed', onUserLeave.bind(null, self.app)); //put user into channel self.app.rpc.chat.chatRemote.add(session, uid, self.app.get('serverId'), rid, true, function(users){ next(null, { users:users }); }); };
服务端将用户加到channel
通过调用rpc方法,将登录的用户加入到channel中。
app.rpc.chat.chatRemote.add(session, uid, app.get('serverId'), function(data){});
其中app是pomelo的应用对象,app.rpc表明了是前后台服务器的Remote rpc调用,后面的参数分别代表服务器的名称、对应的文件名称及方法名。为了实现这个rpc调用,则只需要在对应的chat/remote/中新建文件chatRemote.js,并实现add方法。
remote.add = function(uid, sid, cb){
var channel = channelService.getChannel('pomelo', true);
if(!!channel)
channel.add(uid, sid);
};
在add方法中,首先从pomelo提供的channelService中取出channel,然后将用户加入到channel中即可。这样就完成了一个完整的rpc调用,在pomelo里复杂的rpc调用就是这么简单。
接下来,我们看一下另一段客户端代码
web-server/public/js/client.js
var route = "chat.chatHandler.send"; var target = $("#usersList").val(); if(e.keyCode != 13 /* Return */ ) return; var msg = $("#entry").attr("value").replace("\n", ""); if(!util.isBlank(msg)) { pomelo.request(route, { rid: rid, content: msg, from: username, target: target }, function(data) { $("#entry").attr("value", ""); // clear the entry field. if(target != '*' && target != username) { addMessage(username, target, msg); $("#chatHistory").show(); } }); }
chat/chatHandler.js
/** * Send messages to users * * @param {Object} msg message from client * @param {Object} session * @param {Function} next next stemp callback * */ handler.send = function(msg, session, next) { var rid = session.get('rid'); var username = session.uid.split('*')[0]; var channelService = this.app.get('channelService'); var param = { route: 'onChat', msg: msg.content, from: username, target: msg.target }; channel = channelService.getChannel(rid, false); //the target is all users if(msg.target == '*') { channel.pushMessage(param); } //the target is specific user else { var tuid = msg.target + '*' + rid; var tsid = channel.getMember(tuid)['sid']; channelService.pushMessageByUids(param, [{ uid: tuid, sid: tsid }]); } next(null, { route: msg.route }); };