Pomelo Client

使用pomelo做服務(wù)器開(kāi)發(fā)時(shí)等曼,無(wú)論什么客戶端,只要遵循與服務(wù)器的線上協(xié)議就能夠與服務(wù)器建立通信禁谦。pomelo內(nèi)置sioconnector、hybirdconnector都定義了自己的協(xié)議格式丧蘸。

服務(wù)器通信協(xié)議

配置服務(wù)器通信協(xié)議

$ vim game-server/app.js
const pomelo = require('pomelo');

/**
 * 初始化應(yīng)用
 */
const app = pomelo.createApp();
app.set('name', 'test');

//前端服務(wù)器配置
app.configure('production|development',  'connector', function(){
    //連接配置
    app.set('connectorConfig',
    {
      connector : pomelo.connectors.hybridconnector,
      heartbeat : 3,
      useDict : true,
      useProtobuf : true
    });
});

//開(kāi)啟應(yīng)用
app.start();

process.on('uncaughtException', function (err) {
  console.error(' Caught exception: ' + err.stack);
});

Pomelo支持的通信協(xié)議

在與客戶端通信時(shí)pomelo提供了hybirdconnector和sioconnector触趴,hybirdconnector支持TCP、WebSocket,sioconnector支持socket.io爽冕。實(shí)際編程中,可使用pomelo提供的接口自定義connector乌奇。

前端服務(wù)器 協(xié)議 通信 適用范圍
hybirdconnector pomelo.connectors.hybirdconnector TCP、WebSocket 使用二進(jìn)制通信 移動(dòng)端
sioconnector pomelo.connectors.sioconnector socket.io 使用JSON通信 PC端
udpconnector pomelo.connectors.udpconnector UDP 二進(jìn)制協(xié)議 網(wǎng)路環(huán)境差數(shù)據(jù)包小的環(huán)境
mqttconnector pomelo.connectors.mqttconnector MQTT 二進(jìn)制物聯(lián)網(wǎng)協(xié)議 嵌入式設(shè)備

pomelo內(nèi)部有各種協(xié)議的實(shí)現(xiàn)礁苗,典型的有protobuf试伙、mqtt。mqtt物聯(lián)網(wǎng)協(xié)議的特點(diǎn)是體積小疏叨、效率高、省電卦溢,pomelo+mqtt能實(shí)現(xiàn)單機(jī)30w在線的推送秀又。

Web端API

Web端JavaScript開(kāi)發(fā)庫(kù)

對(duì)于瀏覽器來(lái)說(shuō)单寂,HTML5中已經(jīng)支持了WebSocket宣决,因此使用支持WebSocket的瀏覽器可以直接與服務(wù)器的hybirdconnector建立通信。對(duì)于比較舊的瀏覽器袱讹,還沒(méi)有支持websocket的可使用基于socket.io的方式與服務(wù)器建立連接。因此椒丧,對(duì)于Web端救巷,Pomelo提供了兩套開(kāi)發(fā)庫(kù),分別適用于支持WebSocket的瀏覽器和不支持WebSocket的瀏覽器棒假。

開(kāi)發(fā)庫(kù) 描述
pomelo-jsclient-socket.io 適用于socket.io
pomelo-jsclient-websocket 適用于websocket

無(wú)論是socket.io還是websocket都提供了統(tǒng)一的API

初始化

pomelo.init(params, cb);

客戶端pomelo初始化精盅,在客戶端第一次調(diào)用時(shí)使用。參數(shù)params中需要指定連接的服務(wù)器的主機(jī)地址和端口叹俏,回調(diào)函數(shù)cb在連接成功后會(huì)進(jìn)行回調(diào)。

pomelo.init = function(params, cb){
  pomelo.params = params;
  params.debug = true;
  var host = params.host;
  var port = params.port;

  var url = 'ws://' + host;
  if(port) {
    url +=  ':' + port;
  }

  socket = io(url, {'force new connection': true, reconnect: false});

  socket.on('connect', function(){
    console.log('[pomeloclient.init] websocket connected!');
    if (cb) {
      cb(socket);
    }
  });

  socket.on('reconnect', function() {
    console.log('reconnect');
  });

  socket.on('message', function(data){
    if(typeof data === 'string') {
      data = JSON.parse(data);
    }
    if(data instanceof Array) {
      processMessageBatch(pomelo, data);
    } else {
      processMessage(pomelo, data);
    }
  });

  socket.on('error', function(err) {
    console.log(err);
  });

  socket.on('disconnect', function(reason) {
    pomelo.emit('disconnect', reason);
  });
};

請(qǐng)求服務(wù)

pomelo.request(route, msg, cb);

request用于請(qǐng)求服務(wù)屡谐,route是服務(wù)端的路由愕掏,格式為"xxx.xxx.xxx"顶伞。msg為請(qǐng)求內(nèi)容剑梳,cb響應(yīng)回來(lái)后的回調(diào)函數(shù)阻荒。

參數(shù) 描述
route 服務(wù)端的路由众羡,格式為"xxx.xxx.xxx"。
msg 請(qǐng)求內(nèi)容
cb 響應(yīng)成功后的回調(diào)函數(shù)
pomelo.request = function(route) {
  if(!route) {
    return;
  }
  var msg = {};
  var cb;
  arguments = Array.prototype.slice.apply(arguments);
  if(arguments.length === 2){
    if(typeof arguments[1] === 'function'){
      cb = arguments[1];
    }else if(typeof arguments[1] === 'object'){
      msg = arguments[1];
    }
  }else if(arguments.length === 3){
    msg = arguments[1];
    cb = arguments[2];
  }
  msg = filter(msg,route);
  id++; 
  callbacks[id] = cb;
  var sg = Protocol.encode(id,route,msg);
  socket.send(sg);
};

例如:同網(wǎng)關(guān)服務(wù)器建立連接后 羊壹,向其發(fā)送查詢前端服務(wù)器入口的請(qǐng)求齐婴。

/**
 * 連接gate服務(wù)器
 * 客戶端首先要給gate服務(wù)器查詢一個(gè)connector服務(wù)器,gate給其回復(fù)一個(gè)connector的地址及端口號(hào)
 * */
function queryEntry(data, callback){
    const config = {host:"127.0.0.1", port:3014, log:true};
    pomelo.init(config, function(socket){
        const route = "gate.gateHandler.queryEntry";
        pomelo.request(route, data, function(msg){
            pomelo.disconnect();
            if(!msg){
                msg = {code:500, msg:"error"};
            }
            callback(msg);
        });
    });
}

斷開(kāi)連接

客戶端與服務(wù)器斷開(kāi)連接有兩種可能情妖,一種是心跳超時(shí)诱担,一種是直接斷開(kāi)。

pomelo.disconnect();

disconnect()方法用于Pomelo主動(dòng)斷開(kāi)連接

pomelo.disconnect = function() {
  if(socket) {
    socket.disconnect();
    socket = null;
  }
};

客戶端檢測(cè)主動(dòng)斷開(kāi)

pomelo.on("disconnect", function(){
  console.log("主動(dòng)斷開(kāi)");
});

客戶端檢測(cè)心跳超時(shí)

pomelo.on("heartbeat timeout", function(){
  console.log("心跳超時(shí)");
});

事件監(jiān)聽(tīng)

on()方法用于從EventEmmiter繼承過(guò)來(lái)料睛,用來(lái)對(duì)服務(wù)端的推送做出響應(yīng)摇邦。route用戶可以自定義,格式一般為onXXX居扒。

pomelo.on(route, cb);
EventEmitter.prototype.on = EventEmitter.prototype.addListener;

例如:系統(tǒng)內(nèi)置事件監(jiān)聽(tīng)

pomelo.on("connect", function(){
    console.log("pomelo client connect");
});
pomelo.on("disconnect", function(){
   console.log("pomelo client disconnect");
});
pomelo.on("error", function(){
   console.log("pomelo client error");
});
pomelo.on("heartbeat timeout", function(){
   console.log("pomelo client heartbeat timeout");
});

例如:自定義事件監(jiān)聽(tīng)

pomelo.on("onJoin", function(data){
   console.log("onJoin", data);
});
pomelo.on("onKick", function(data){
   console.log("onKick", data);
});
pomelo.on("onChat", function(data){
   console.log("onChat", data);
});

封裝

使用ES7的async/await封裝pomelo客戶端的request方法

function pomelo_init_request(host, port, route, param){
    return new Promise((resolve, reject)=>{
       pomelo.init({host:host, port:port, log:true}, socket=>{
           pomelo.request(route, param, res=>{
               console.log(res);
                if(res.code === 200){
                    resolve({error:false, data:res.data, message:res.message});
                }else{
                    reject({error:true, message:res.message});
                }
               //pomelo.disconnect();
           });
       });
    });
}
function pomelo_request(route, param){
    return new Promise((resolve, reject)=>{
       pomelo.request(route, param, res=>{
           console.log(res);
            if(res.code === 200){
                resolve({error:false, data:res.data, message:res.message});
            }else{
                reject({error:true, message:res.message});
            }
           //pomelo.disconnect();
       });
    });
}

使用封裝后的方法

function id(min=100000, max=1000000){
    return Math.round(Math.random()*(max - min)) + min;
}

const aid = id();
const rid = 222222;
async function main(){
    let result;
    result = await pomelo_init_request("127.0.0.1", 3014, "gate.gateHandler.queryEntry", {aid:aid});
    if(!result.error){
        await pomelo_init_request(result.data.host, result.data.port, "connector.chatHandler.join", {aid:aid, rid:rid});
    }
    await pomelo_request("chat.chatHandler.send", {target:"*", content:"hello world"});
}
main();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市立哑,隨后出現(xiàn)的幾起案子铛绰,更是在濱河造成了極大的恐慌,老刑警劉巖捂掰,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異这嚣,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吏垮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門膳汪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人遗嗽,你說(shuō)我怎么就攤上這事鼓蜒。” “怎么了都弹?”我有些...
    開(kāi)封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵缔杉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我或详,道長(zhǎng),這世上最難降的妖魔是什么椒振? 我笑而不...
    開(kāi)封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任梧乘,我火速辦了婚禮,結(jié)果婚禮上选调,老公的妹妹穿的比我還像新娘。我一直安慰自己仁堪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布鸟辅。 她就那樣靜靜地躺著,像睡著了一般匪凉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上再层,一...
    開(kāi)封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音萨脑,去河邊找鬼饺饭。 笑死,一個(gè)胖子當(dāng)著我的面吹牛瘫俊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播扛芽,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼登下!你這毒婦竟也來(lái)了叮喳?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤畔濒,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后侵状,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡趣兄,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年艇潭,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暴区。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仙粱,死狀恐怖彻舰,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情刃唤,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布硬霍,位于F島的核電站,受9級(jí)特大地震影響唯卖,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拜轨,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一橄碾、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧法牲,春花似錦、人聲如沸木柬。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)速挑。三九已至,卻和暖如春姥宝,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背套么。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胚泌,地道東北人省咨。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓零蓉,卻偏偏與公主長(zhǎng)得像穷缤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子津肛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349