Giter Site home page Giter Site logo

hprose / hprose Goto Github PK

View Code? Open in Web Editor NEW
367.0 39.0 34.0 114 KB

HPROSE is short for High Performance Remote Object Service Engine. It's a serialize and RPC library, the serialize library of hprose is faster, smaller and more powerful than msgpack, the RPC library is faster, easier and more powerful than thrift.

Home Page: http://hprose.com

rpc rpc-protocol serialization-format hprose cross-language rpc-library cross-platform service-engine semi-text cross-browser cross-device cross-domain serialization serialize

hprose's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hprose's Issues

返回服务函数(方法)列表的更改

Hprose 旧版本协议中,当提交的请求中只包含结束符 'z' 时,返回一个以 'F' 开头的方法名列表。

在这种方式下,无法用一个统一的编解码器来处理所有请求和返回结果,这使得让用户自己定制编解码器这个需求变得十分困难,即使强行实现,也会让编解码器在接口方面显得很不优雅。

所以,在 Hprose 3.0 中,决定使用跟远程调用一样的方式来获取方法名列表。

请求:

Cu~z

响应:

Ra4{u~u#u*s5"hello"}z

这里获取服务列表的方法名用一个特殊字符 ~ 表示,这样可以防止跟正常的远程调用方法名冲突。

返回的结果如同正常调用一样返回一个字符串数组的结果。跟原来相比,仅返回的开始标记不一样,后面的内容是一样的。因此不会增加冗余。

上面的返回列表里面我们看到有3个特殊字符串的方法名,它们分别是 ~#*,其中 ~ 就是上面获取服务方法列表的方法名,# 是 hprose 2.0 中添加推送功能时,增加的用来从服务器端返回客户端唯一标识的方法名。* 是从一开始就有的用来表示统一处理缺失方法的方法名。

另外,hprose 3.0 中还会增加一个用特殊字符 ! 表示的反向调用的方法名(#10)。

以后如果需要扩展特殊功能,也会采用这种方式,只要选择的特殊字符避免与上面 4 个冲突就可以了。

关于 Hprose 3.0 通信协议设计方案的讨论

Hprose 从 2008 年开始设计开发,从最初仅支持 HTTP,到后来增加了 WebSocket、TCP、UnixSocket 支持,以及在 Hprose 2.0 中增加了服务器推送等功能。这些都是在最初通信协议的设计下完成的。并未对通信协议本身做以修改。因此,Hprose 2.0 实现可以完全兼容 Hprose 1.x 的实现。

虽然 Hprose 2.0 目前已经满足了大多数开发者的需求,但是本着可以做到更好的目的,特开此贴,希望能够汇总广大 Hprose 开发者、用户及爱好者的意见建议和新需求,如果可能,将会把它们添加到下一版的 Hprose 3.0 中去。

所以,如果你有什么新的需求和想法,请不要吝啬你的文字,你可以开一个新的 issue,把你想说的内容用最详尽的方式表达出来,包括需求描述,应用场景描述,现有协议和实现为何无法满足,具体的改进和实现的细节等等。之后,你可以将你开的 issue 发到本贴的回复中。具体做法可以参照二楼回复。

格式不要求统一,但是请不要一句话带过,不然除了你自己,谁也不知道你想要的是什么。

欢迎大家积极参与讨论。

php 7.3 hprose扩展安装编译失败

php 7.3 hprose扩展安装编译失败, 错误代码:

creating libtool
appending configuration tag "CXX" to libtool
configure: creating ./config.status
config.status: creating config.h
running: make
/bin/bash /tmp/pear/temp/pear-build-defaultuseraiheej/hprose-1.6.6/libtool --mod e=compile cc -I. -I/tmp/pear/temp/hprose -DPHP_ATOM_INC -I/tmp/pear/temp/pear-b uild-defaultuseraiheej/hprose-1.6.6/include -I/tmp/pear/temp/pear-build-defaultu seraiheej/hprose-1.6.6/main -I/tmp/pear/temp/hprose -I/usr/local/include/php -I/ usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/ph p/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -fsta ck-protector-strong -fpic -fpie -O2 -DHAVE_CONFIG_H -fstack-protector-strong -f pic -fpie -O2 -c /tmp/pear/temp/hprose/php_hprose.c -o php_hprose.lo
mkdir .libs
cc -I. -I/tmp/pear/temp/hprose -DPHP_ATOM_INC -I/tmp/pear/temp/pear-build-defau ltuseraiheej/hprose-1.6.6/include -I/tmp/pear/temp/pear-build-defaultuseraiheej/ hprose-1.6.6/main -I/tmp/pear/temp/hprose -I/usr/local/include/php -I/usr/local/ include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/ usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -fstack-protecto r-strong -fpic -fpie -O2 -DHAVE_CONFIG_H -fstack-protector-strong -fpic -fpie -O 2 -c /tmp/pear/temp/hprose/php_hprose.c -fPIC -DPIC -o .libs/php_hprose.o
/bin/bash /tmp/pear/temp/pear-build-defaultuseraiheej/hprose-1.6.6/libtool --mod e=compile cc -I. -I/tmp/pear/temp/hprose -DPHP_ATOM_INC -I/tmp/pear/temp/pear-b uild-defaultuseraiheej/hprose-1.6.6/include -I/tmp/pear/temp/pear-build-defaultu seraiheej/hprose-1.6.6/main -I/tmp/pear/temp/hprose -I/usr/local/include/php -I/ usr/local/include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/ph p/Zend -I/usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -fsta ck-protector-strong -fpic -fpie -O2 -DHAVE_CONFIG_H -fstack-protector-strong -f pic -fpie -O2 -c /tmp/pear/temp/hprose/hprose_common.c -o hprose_common.lo
cc -I. -I/tmp/pear/temp/hprose -DPHP_ATOM_INC -I/tmp/pear/temp/pear-build-defau ltuseraiheej/hprose-1.6.6/include -I/tmp/pear/temp/pear-build-defaultuseraiheej/ hprose-1.6.6/main -I/tmp/pear/temp/hprose -I/usr/local/include/php -I/usr/local/ include/php/main -I/usr/local/include/php/TSRM -I/usr/local/include/php/Zend -I/ usr/local/include/php/ext -I/usr/local/include/php/ext/date/lib -fstack-protecto r-strong -fpic -fpie -O2 -DHAVE_CONFIG_H -fstack-protector-strong -fpic -fpie -O 2 -c /tmp/pear/temp/hprose/hprose_common.c -fPIC -DPIC -o .libs/hprose_common.o
/tmp/pear/temp/hprose/hprose_common.c: In function '__get_fcall_info_cache':
/tmp/pear/temp/hprose/hprose_common.c:166:46: warning: format '%s' expects argum ent of type 'char *', but argument 4 has type 'zend_string * {aka struct _zend_s tring *}' [-Wformat=]
"Method %s::%s() does not exist", ce->name, fname);
^
/tmp/pear/temp/hprose/hprose_common.c:202:8: error: 'zend_fcall_info_cache {aka struct _zend_fcall_info_cache}' has no member named 'initialized'
fcc.initialized = 1;
^
/tmp/pear/temp/hprose/hprose_common.c: In function '__create_php_object':
/tmp/pear/temp/hprose/hprose_common.c:764:12: error: 'zend_fcall_info_cache {aka struct _zend_fcall_info_cache}' has no member named 'initialized'
fcc.initialized = 1;
^
make: *** [Makefile:196: hprose_common.lo] Error 1
ERROR: `make' failed

新增客户端和服务器端传递共享数据的功能

在 Hprose 1.x 和 2.0 版本中,每个调用的上下文对象都是在客户端和服务器端独立传递的,虽然这在一定程度上能够满足大多数情况的需要。但是有时我们还希望能够通过方法参数和返回结果以外的方式在客户端和服务器之间传递某些共享数据信息,实现类似于 HTTP Header 一样的功能。

下面我列出两种解决方案,请大家投票。

更多协议的支持如KCP和QUIC

KCP是为流速设计的(单个数据包从一端发送到一端需要多少时间),以10%-20%带宽浪费的代价换取了比 TCP快30%-40%的传输速度。所以在网络欠佳时KCP有比TCP更好的表现。
目前KCP已经有不少语言的实现:
1、C:kcp
2、Java-netty:kcp-netty
3、golang:kcp-go
4、rust:kcp
5、C#:kcp-csharp
6、Node.JS:node-kcp

QUIC协议实现比较复杂,没找到合适的实现。要适配到hprose可能过于困难,暂时不用考虑这个。

Hprose 推送功能的改进

Hprose 2.0 中增加了服务器推送的功能。但是该功能目前仍然有一些问题需要解决:

  1. 客户端超时必须要大于服务器端超时,否则,客户端可能会收不到或丢失部分服务器端推送的数据。

  2. 当客户端短时间内关闭并重启,且使用同一个客户端 id 来订阅推送主题时,客户端会收不到或丢失部分服务器端的推送数据。

  3. 当服务器对客户端进行高频数据推送时,客户端如果来不及响应,客户端会丢失部分服务器端的推送数据。

4、无法推送 null,无法推送异常。

5、无法快速退订主题。

要解决这些问题,就需要对现有实现做出修改,下面是如何修改的一些想法。

TCP/Unix 套接字绑定的改进

Hprose 2.0 中增加全双工和半双工的 TCP/Unix Socket 绑定实现。

但是因为对于数据长度没有校验,因此如果服务器收到随便乱发的一堆数据,会很容易因为长度问题导致崩溃。

因此,Hprose 3.0 中希望对这种情况做出改善。

首先半双工相对于全双工通讯除了实现简单一些,没有任何优势,因此可以考虑 Hprose 3.0 中不在区分全双工和半双工通讯,统一改为全双工通讯。

其次,原来全双工的通讯的头部有8个字节用来标识数据长度和请求唯一标识,这 8 个字节的意义和格式保持不变,然后在这 8 个字节之前,再加 4 个字节的校验,其值为这 8 个字节的 crc32 值。

然后通过这个校验就可以有效的排除乱发的数据,这样,即使要攻击服务器,也需要精心构造请求格式。

其次在实现上,服务器端可以增加请求长度最大值的限制,超过这个限制的请求,在读取完请求长度的 4 个字节之后,就直接关闭连接就可以了。这属于实现部分要做的事情,在通信协议中不做体现。

剩下的包体部分,可以是任意内容,这样既可以传输 hprose 通讯数据,也可以传输自定义加密、压缩的 hprose 通讯数据,甚至可以传输 jsonrpc 格式的数据,只要有响应的解码器或中间件来解码就可以了。

为 Hprose 新增反向调用的功能

应用场景

有些时候,我们需要在客户端之间相互调用,或者希望服务器端可以调用客户端发布的方法。如果 RPC 提供了反向调用的能力,就可以实现客户端和服务器端的双向调用了。

实现原理

在 Hprose 现有的 RPC 协议基础上,通过对参数和返回值的特殊约定,将调用和返回过程反转。

具体实现

首先跟推送类似,客户端首先发送一个请求给服务器,目的仅仅是让服务器可以反向传递请求,客户端请求格式如下:

Hm1{s2"id"s36"AFA7F4B1-A64D-46FA-886F-EF6432AD69A3"}Cu!z

H 部分是客户端传递给服务器端共享数据,其中可以包含多项内容,但是对于反向调用来说,id 部分是必选项,它表示客户端唯一 id。

C 部分原本是表示客户端对服务器的 RPC 调用请求,这里采用了一个特殊的方法名(!)来表示这是一个反向调用请求。

当服务器没有对客户端进行反向调用时,该连接一直保持,直到服务器超时,或客户端超时。

如果服务器超时,服务器返回:

Ra{}z

Rez

表示服务器端没有发起对客户的反向调用。客户端收到该响应后,重新发起前面的请求。

如果客户端超时,客户端也重新发起前面的请求。当服务器端收到客户端的第二个请求之后,对前一个请求返回响应:

Rnz

客户端收到该响应后,直接忽略,不再重新发起请求,这样做可以避免产生无效的交替请求。

当服务器有对客户端进行反向调用时,服务器返回响应:

Ra<n>{<call-1><call-2>...<call-n>}z

也就是说,服务器端可以批量发起对客户端的调用,这在服务器短时间内对客户端进行高频调用的时候会很有用,这样可以有效的减少服务器和客户端直接的通信次数。

当服务器对客户端仅有一个反向调用时,响应为:

Ra1{<call>}z

其中 <call> 跟前面批量调用中的 <call-1><call-2>, <call-n> 格式相同。<call> 的格式如下:

a3{<call-id><call-name><call-args>}

也就是说,<call> 是一个三元组。<call-id><call-name><call-args> 都是通过 Hprose 序列化之后的数据。

<call-id> 表示服务器端对客户端反向调用的编号,整数类型。因为服务器启动可能会对同一个客户端发起多个调用,而调用返回的顺序跟调用的顺序并不一定是一致的,调用和结果的传递可能在一个连接上,也可以不在一个连接上,因此无法通过连接来确认客户端返回结果跟服务器发起调用直接的关系,但是通过携带的这个编号,就可以将服务器反向调用跟客户端返回的结果进行一对一匹配了。

<call-name> 表示服务器对客户端反向调用的方法名。字符串类型。

<call-args> 表示服务器对客户端反向调用的参数。数组类型。

当客户端收到服务器端的反向调用后,在处理调用之前,再次发起前面的请求,这样服务器不需要等待前面的请求处理结束,就可以发起新的反向调用了。

客户端执行完反向调用的方法后,将结果以如下形式传递给服务器端:

H<header>Cu=a1{a<n>{<data-1><data-2>...<data-n>}}z

<header> 部分如前所述,不再重复。当仅有一个结果传递给服务器端时,请求格式就变成了:

H<header>Cu=a1{a1{<data>}}z

返回结果之所以被作为一个数组参数返回,是为了便于服务器端解析,如果是去掉最外层的 a1{...},在服务器端该参数就会变成变长参数,会增加服务器端编写的复杂度。为了降低实现的复杂度,便于在各种语言中都能方便实现,故而把它仅作为一个参数传递。

<data> 跟批量结果的 <data-1><data-2><data-n> 格式相同。<data> 的格式如下:

a3{<call-id><call-result>n}

当调用发生异常时,格式为:

a3{<call-id>n<call-error>}

<call-error> 为字符串类型,其值为 n 时表示没有错误,因此服务器端可以根据其值进行区分。

服务器端处理完之后,直接返回:

Rnz

客户端收到该响应后,直接忽略。反向调用结束。

客户端跟服务器端的连接通过 ! 请求一直保持,如果客户端想要主动停止对服务器端提供服务,需要发起一个 !! 请求,该请求同样没有参数,服务器端收到之后,返回 Rnz。同时与该 id 对应的 ! 请求也返回 Rnz。客户端的 ! 请求收到该响应之后,停止循环。客户端提供的反向调用服务结束。

注意:

服务器端向客户端发起反向调用时,在 R 标记之前,也可以跟随 H 标记来传递共享数据。

批量调用在 Hprose 3.0 中使用插件方式实现。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.