pomelo 协议
分析的是hybridconnector,使用的chatofpomelo-websocket(pomelo为0.7.0)
參考:https://github.com/NetEase/pomelo/wiki/Pomelo-通讯协议
http://cnodejs.org/topic/51395fd0df9e9fcc5882576c
client握手:
pomelo在init时候,创建WebSocket连接。并定义onopen onmessage回调,
连接建立后,onopen被回调。client首先发送握手包var obj = Package.encode(Package.TYPE_HANDSHAKE, Protocol.strencode(JSON.stringify(handshakeBuffer)));
參数为。假设version在client有缓存,将使用缓存{
'sys': {
'version': '1.1.1',
'type': 'js-websocket'
},
'user': {
// any customized request data
}
}
这种方法中,package格式为type。length。body。传入的參数为type和body,
服务端发回message,在onmessage中处理server到client的握手响应,服务端发回的參数
{
'code': 200, // result code
'sys': {
'heartbeat': 3, // heartbeat interval in second
'dict': {}, // route dictionary
'protos': {} // protobuf definition data
},
'user': {
// any customized response data
}
}
并分发到handshake处理。首先缓存dict和protos,然后发回var obj = Package.encode(Package.TYPE_HANDSHAKE_ACK);握手ack,至此握手完成
client打包:
Package分为header和body两部分。
Header描写叙述package包的类型和包的长度。body则是须要传输的数据内容。
详细格式參考https://github.com/NetEase/pomelo/wiki/Pomelo-通讯协议
package的body部分发送的是Message,消息头分为三部分,flag,message id,route。
详细格式參考https://github.com/NetEase/pomelo/wiki/Pomelo-通讯协议
Package.encode,打包函数比較简单,仅仅是转换大小端
Message.encode。Message的打包函数,第一步是计算包长度,message id可变,要计算,是否有路由。要计算。加上发送的内容,就是总长度,然后创建buffer填充内容。
填充内容时候,假设有路由压缩,则在填充路由的时候。填充替换过的路由。
pomelo.encode 用户数据打包函数。
这个打包的结果是Message.encode中的msg,这个函数用了处理路由压缩和protobuf压缩。
假设clientProtos中配置了路由。将用 protobuf.encode(route, msg);打包内容。假设dict定义了路由,将替换路由
程序运行的顺序刚好与以上介绍反过来,先内层后外层
client解包:
Package.decode,解包出类型和长度
Message.decode。解包id,路由。和body,注意id和路由可能不存在
pomelo.decode。假设有id。则说明是request,直接从routeMap中替换路由,然后deCompose,路由有compressRoute,则替换路由。serverProtos中要求打包路由,则用protobuf.decode解包内容
解包刚好是正常的运行顺序,先外层后内层
服务端:
使用的hybridconnector中的websocket链接
hybridconnector和hybridsocket是pomelo封装的server和socket。switch是转发。
wsprocessor是websocket处理的文件,commands目录是握手。心跳处理的逻辑
hybridconnector用 this.tcpServer = net.createServer();接受连接。switch分发tcp和websocket。
到processor处理
对于websocket的连接建立过程:
1:switch中的tcpServer转发connection到newSocket处理。newSocket将connection转发给wsprocessor处理
2:Processor.prototype.add中。httpServer分发connection消息(由于pomelo自己用net接受的连接,所以要自己用httpserver解析http协议),
http.js中用connectionListener函数处理connection消息。仅仅是为socket加入了一下处理函数(ondata下一步会用到),
3:由于socket.ondata存在,所以直接调用,在http.js中看到ondata相应websocket来说,是为了分发upgrade消息
4:在httpserver的外层还有WebSocketServer,WebSocketServer在创建的时候,会注冊httpserver的upgrade消息,用于建立websocket连接,同一时候分发connection消息
5:processor在创建的时候。注冊了websocketserver的connection消息,并再次分发
6:switch转发了processor的connection消息
7:hybridconnector注冊了switch的connection消息,用socket封装成hybridsocket。并为hybridsocket注冊handshake heartbeat disconnect closing消息,同一时候分发connection消息
8:组件connector在初始化时。注冊了hybridconnector的connection消息,用bindEvents,为hybridsocket注冊了disconnect error message消息。至此连接建立
对于websocket的握手过程:
1:消息的起源处是,socket分发message消息。在hybridsocket中,收到消息,用Package.decode(msg)解包,解包函数与client一致,握手请求分发到handleHandshake。分发传入的socket为hybridsocket类型
2:handleHandshake将上一步解析出的msg,将body通过JSON.parse(protocol.strdecode(msg.body))转成json,用handshake消息分发出去
3:在hybridconnector中,參考【websocket的连接建立过程】7。连接时候已经注冊了handshake处理方法。将转发给handshake.handle
4:在commands的handshake中。參数heartbeat dict sys被收集,通过服务端的握手包返回给client
5:但服务端收到握手ack包时。服务端回复client心跳包,(socket.emit('heartbeat');)。至此握手完毕
服务端心跳逻辑:
1:握手完毕后,hybridsocket分发heartbeat消息,在commands中的heartbeat处理,在heartbeats字典中。存储计时器,将在心跳时间后,发送心跳包。并注冊超时函数
2:当收到client的心跳包后。在hybridsocket处handleHeartbeat中处理。分发heartbeat消息。
在commands中的heartbeat中。要先清理超时回调,然后同1
服务端响应request:
1:消息的起源处是,socket分发message消息。在hybridsocket中,收到message消息,用Package.decode(msg)解包,解包函数与client一致,通过hybridsocket分发解析后的msg
2:參考【websocket的连接建立过程】8,在connector处理了解析后的msg,首先调用 self.connector.decode(msg);hybridconnector中的decode与client的解包一致,
先调用Message.decode(msg.body);然后替换路由。和用protobuf解压缩
3:然后handleMessage。将解析后的请求,分发到相应的server处理,回调的结果通过self.send(msg.id, msg.route, resp, [session.id], {isResponse: true}, function() {});返回给client
send中会将发送的内容通过emsg = this.connector.encode(reqId, route, msg);打包成message,代码在hybridconnector中,与client逻辑同样
4:connector的send方法。通过组件__pushScheduler__发送,并在下一帧调用回调函数(reqest的回调为空函数)
5:组件__pushScheduler__发送,不论是广播还是推送,都是通过sessionService.sendMessage发送,然后调用session的send方法
6:sessionservice逻辑中。session是在【websocket的连接建立过程】8中的bindevents中生成的。成员变量__socket__是hybridsocket,所以。session的send方法通过hybridsocket的send实现
7:hybridsocket的send中this.sendRaw(Package.encode(Package.TYPE_DATA, msg)); 至此服务端完毕对request的响应
服务端的push不再详说
pomelo 协议的更多相关文章
- 用Pomelo 搭建一个简易的推送平台
前言 实际上,个人感觉,pomelo 目前提供的两个默认sioconnector和hybridconnector 使用的协议并不适合用于做手机推送平台,在pomelo的一份公开ppt里面,有提到过, ...
- pomelo架构概览
pomelo之所以简单易用.功能全面,并且具有高可扩展性.可伸缩性等特点,这与它的技术选型和方案设计是密不可分的.在研究大量游戏引擎设计思路基础上,结合以往游戏开发的经验,确定了pomelo框架的设计 ...
- Nodejs学习笔记(十六)--- Pomelo介绍&入门
目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json 配置servers.json ...
- 八问WebSocket协议:为你快速解答WebSocket热门疑问
一.引言 WebSocket是一种比较新的协议,它是伴随着html5规范而生的,虽然还比较年轻,但大多主流浏览器都已经支持.它使用方面.应用广泛,已经渗透到前后端开发的各种场景中. 对http一问一答 ...
- 脑残式网络编程入门(三):HTTP协议必知必会的一些知识
本文原作者:“竹千代”,原文由“玉刚说”写作平台提供写作赞助,原文版权归“玉刚说”微信公众号所有,即时通讯网收录时有改动. 1.前言 无论是即时通讯应用还是传统的信息系统,Http协议都是我们最常打交 ...
- Pomelo分布式游戏服务器框架
Pomelo介绍&入门 目录 前言&介绍 安装Pomelo 创建项目并启动 创建项目 项目结构说明 启动 测试连接 聊天服务器 新建gate和chat服务器 配置master.json ...
- pomelo RPC调用时新增字段缺失
接触pomelo开发一个月,正式开始参与项目开发有10天,遇到很多细节的坑,今天讲讲标题:后端服务器节点之间的rpc调用过程中,返回的数据中新增字段缺失问题. 先讲结果:原因是该rpc调用已经采用了p ...
- Nodejs学习笔记(十六)—Pomelo介绍&入门
前言&介绍 Pomelo:一个快速.可扩展.Node.js分布式游戏服务器框架 从三四年前接触Node.js开始就接触到了Pomelo,从Pomelo最初的版本到现在,总的来说网易出品还算不错 ...
- HTTP协议系列(1)
一.为什么学习Http协议 首先明白我们为什么学习HTTP协议,也就是说明白HTTP协议的作用.HTTP协议是用于客户端与服务器之间的通讯.明白了HTTP协议的作用也就知道了为什么要学习H ...
随机推荐
- .net c# 提交包含文件file 的form表单 获得文件的Stream流
1.前台html代码 要写一个有id的form,可是不能有runat="server"属性.由于一个页面中,有这个属性的form表单仅仅能有一个. 再要有一个有name的ifram ...
- js 乱码解决方案
如果网页编码规则是utf-8,即在网页头部中可以看到如下代码: 那么js文件中如果有中文字,调用输出时就会出现乱码.解决此个问题的办法如下: 即在引用javascript输出的地方加上charset= ...
- BZOJ 1231: [Usaco2008 Nov]mixup2 混乱的奶牛( dp )
状压dp dp( x , S ) 表示最后一个是 x , 当前选的奶牛集合为 S , 则状态转移方程 : dp( x , S ) = Σ dp( i , S - { i } ) ( i ∈ S , ...
- python2.7_2.2_在套接字服务器上使用ForkingMixIn
Linux系统下才能用本程序.因为有Frok新的进程.... 代码如下: # -*- coding: utf-8 -*- import os import socket import threadin ...
- python--data type
1.Python中常见的数据类型有: 数据类型 内建函数 整型 int(),long() 浮点型 float() 字符串型 str() 列表 list() 元组 t ...
- 如何用一个语句判断一个整数是不是二的整数次幂——从一道简单的面试题浅谈C语言的类型提升(type promotion)
最近招聘季,看JULY大哥的面试100题时,碰到这么一个扩展问题: 如何用一个语句判断一个整数是不是二的整数次幂?(此题在编程之美也有) easy, 2的整数次幂的二进制形式只有一个1,只要用i和i- ...
- HTTPS的学习总结
HTTPS学习总结 简述 HTTPS对比HTTP就多了一个安全层SSL/TLS,具体就是验证服务端的证书和对内容进行加密. 先来看看HTTP和HTTPS的区别 我用AFN访问http下的httpbin ...
- oracle累计求和
//将当前行某列的值与前面所有行的此列值相加,即累计求和: //方法一: with t as( select 1 val from dual union all select 3 ...
- 转:JS线程和JS阻塞页面加载的问题
前几日写了一篇文章,介绍了js阻塞页面加载的问题.当时是通过例子来验证的.今天,我介绍一下浏览器内核,从原理上介绍一下js阻塞页面加载的原因. 浏览器的内核是多线程的,它们在内核制控下相互配合以保持同 ...
- 自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
Nginx比apache要好,优点很多,随便去搜寻引擎找一下就能找到一大把资料,这不是我们讨论的重点,我们的重点是自己做一个运行组合! 為何我不從網上下載一個別人已經封裝好的現成的版本呢?因為 ...