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);
});
});
初始化pomelo.init ()執行個體,通過執行個體pomelo.request 調用伺服器 connector.entryHandler.enter 位置的鈎子,回調成功,則建立聊天室等應用,這是用戶端對伺服器端發出的請求,讓我們看看服務端到底做了什麼?
字元串’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
});
});
};
引用wiki裡面的話
服務端将使用者加到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.send,讓我們看看伺服器的程式到底怎麼處理的
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
});
};
關于這段代碼,wiki描述并不詳細,也是我接下來篇章重點分析的,另外還會分析一下,怎麼編寫鈎子函數是如何處理請求的,還是session等管理。今天就這樣結束吧。