-
connector:frontend前端服务器,承载连接,并把请求转发到后端的服务器群
-
gate:客户端线连接gate服务器,然后再由gate决定客户端和哪个connector连接
-
chat:backend后端服务器,真正处理业务逻辑的地方
一、登陆
1: $("#login").click(function () {
2: username = $("#loginUser").attr("value");
3: rid = $('#channelList').val();//Channel的ID
4:
5: if (username.length > 20 || username.length == 0 || rid.length > 20 || rid.length == 0) {
6: showError(LENGTH_ERROR);
7: return false;
8: }
9:
10: if (!reg.test(username) || !reg.test(rid)) {
11: showError(NAME_ERROR);
12: return false;
13: }
14:
15://query entry of connection
16: queryEntry(username, function (host, port) {//host,post是gate服务器分配给该客户端的connector服务器的host和clientPort
17: pomelo.init({//pomeloclient.js中的init()方法
18: host: host,
19: port: port,
20: log: true
21: }, function () {//根据返回的connector服务器的host和port,连接connector
22: var route = "connector.entryHandler.enter";
23: pomelo.request(route, {//向connector的服务器发送username和channel(roomid = rid)
24: username: username,
25: rid: rid
26: }, function (data) {//data是connector返回给客户端的数据(对象),是同一channel的用户列表
27: if (data.error) {
28: showError(DUPLICATE_ERROR);
29: return;
30: }
31: setName();
32: setRoom();
33: showChat();
34: initUserList(data);
35: });
36: });
37: });
38: });
1:function queryEntry(uid, callback) {
2:var route = 'gate.gateHandler.queryEntry';
3: pomelo.init({//连接game服务器
4: host: window.location.hostname,
5: port: 3014, <!--servers.json下的gate的中clientPort为3014-->
6: log: true
7: }, function () {
8: pomelo.request(route, {
9: uid: uid
10: }, function (data) {//data是gate服务器返回给客户端的数据(对象)
11: pomelo.disconnect();//断开gate服务器,连接connector服务器
12: if (data.code === 500) {
13: showError(LOGIN_ERROR);
14: return;
15: }
16: callback(data.host, data.port);//调用回调函数 并将data数据传给回调方法
17: });
18: });
19: };
1: handler.queryEntry = function(msg, session, next) {
2: var uid = msg.uid;
3: if(!uid) {//uid为空 说明用户不存在
4: next(null, {
5: code: 500
6: });
7: return;
8: }
9:// get all connectors 获取所有的connector
10:var connectors = this.app.getServersByType('connector');
11:if(!connectors || connectors.length === 0) {
12: next(null, {
13: code: 500
14: });
15: return;
16: }
17:// select connector
18:var res = dispatcher.dispatch(uid, connectors);//根据算法 返回一个服务器
19: next(null, {
20: code: 200,
21: host: res.host,
22: port: res.clientPort
23: });//将该服务器的host和客户端端口clientPort返回给客户端
24: };
1: var crc = require('crc');
2:
3: module.exports.dispatch = function(uid, connectors) {
4: var index = Math.abs(crc.crc32(uid)) % connectors.length;
5: return connectors[index];
6: };
1: handler.enter = function(msg, session, next) {
2: var self = this;
3: var rid = msg.rid;
4: var uid = msg.username + '*' + rid
5: var sessionService = self.app.get('sessionService');
6:
7://duplicate log in 如果session中已经存在sessionService 说明已登陆
8: if( !! sessionService.getByUid(uid)) {
9: next(null, {
10: code: 500,
11: error: true
12: });
13: return;
14: }
15:
16: session.bind(uid);//将uid(username*rid)绑定到当前的session
17: session.set('rid', rid);//session.settings[rid] = rid;
18: session.push('rid', function(err) {
19:if(err) {
20: console.error('set rid for session service failed! error is : %j', err.stack);
21: }
22: });
23: session.on('closed', onUserLeave.bind(null, self.app));//监听“close”事件 调用onUserLeave()
24:
25://put user into channel
26: self.app.rpc.chat.chatRemote.add(session, uid, self.app.get('serverId'), rid, true, function(users){
27: next(null, {//得到的user是同一channel的用户列表(数组),将这用户列表传给客户端
28: users:users
29: });
30: });
31: };
1:ChatRemote.prototype.add = function(uid, sid, name, flag, cb) {
2:var channel = this.channelService.getChannel(name, flag);
3:var username = uid.split('*')[0];
4:var param = {
5: route: 'onAdd',
6: user: username
7: };
8: channel.pushMessage(param);//Push message to all the members in the channel
9:
10:if( !! channel) {
11: channel.add(uid, sid);
12:}
13:
14:cb(this.get(name, flag));//this.get()返回(name,flag)标记的Channel的用户
15: }
1: ChatRemote.prototype.get = function(name, flag) {
2:var users = [];
3:var channel = this.channelService.getChannel(name, flag);
4:if( !! channel) {
5: users = channel.getMembers();
6:}
7:for(var i = 0; i < users.length; i++) {
8: users[i] = users[i].split('*')[0];
9: }
10:return users;
11: };
-
客户端连接gate服务器,gate返回给客户端connector的port和clientPort
-
客户端连接connector服务器,connector将新登录的用户添加到channel里,通知channel里的所用用户,并返回该channel的所有用户名
-
客户端根据得到的用户名,更新界面
注意:
pomelo是服务器框架, 适合做各种类型的游戏和实时应用, 当然很适合做手机游戏。客户端跟pomelo没关系,所以不存在好不好写的问题。web-server可以认为是HTML 5游戏的客户端,如果做移动游戏可以忽略之。