php实现的一个简单json rpc框架实例


Posted in PHP onMarch 30, 2015

json rpc 是一种以json为消息格式的远程调用服务,它是一套允许运行在不同操作系统、不同环境的程序实现基于Internet过程调用的规范和一系列的实现。这种远程过程调用可以使用http作为传输协议,也可以使用其它传输协议,传输的内容是json消息体。

下面我们code一套基于php的rpc框架,此框架中包含rpc的服务端server,和应用端client;

(一)PHP服务端RPCserver jsonRPCServer.php

class jsonRPCServer {

    /**

     *处理一个request类,这个类中绑定了一些请求参数

     * @param object $object

     * @return boolean

     */

    public static function handle($object) {

       // 判断是否是一个rpc json请求

        if ($_SERVER['REQUEST_METHOD'] != 'POST' || empty($_SERVER['CONTENT_TYPE'])

            ||$_SERVER['CONTENT_TYPE'] != 'application/json') {

            return false;

        }

        // reads the input data

        $request = json_decode(file_get_contents('php://input'),true);

        // 执行请求类中的接口

        try {

            if ($result = @call_user_func_array(array($object,$request['method']),$request['params'])) {

                $response = array ( 'id'=> $request['id'],'result'=> $result,'error'=> NULL );

            } else {

                $response = array ( 'id'=> $request['id'], 'result'=> NULL,

                                        'error' => 'unknown method or incorrect parameters' );}

        } catch (Exception $e) {

            $response = array ('id' => $request['id'],'result' => NULL, 'error' =>$e->getMessage());

        }

       // json 格式输出

        if (!empty($request['id'])) { // notifications don't want response

            header('content-type: text/javascript');

            echo json_encode($response);

        }

        return true;

    }

}

(二)Rpc客户端,jsonRPCClient.php

<?php

/*

 */

class jsonRPCClient {
    private $debug;

    private $url;

    // 请求id

    private $id;

    private $notification = false;

    /**

     * @param $url

     * @param bool $debug

     */

    public function __construct($url,$debug = false) {

        // server URL

        $this->url = $url;

        // proxy

        empty($proxy) ? $this->proxy = '' : $this->proxy = $proxy;

        // debug state

        empty($debug) ? $this->debug = false : $this->debug = true;

        // message id

        $this->id = 1;

    }
    /**

     *

     * @param boolean $notification

     */

    public function setRPCNotification($notification) {

        empty($notification) ? $this->notification = false  : $this->notification = true;

    }
    /**

     * @param $method

     * @param $params

     * @return bool

     * @throws Exception

     */

    public function __call($method,$params) {

        // 检验request信息

        if (!is_scalar($method)) {

            throw new Exception('Method name has no scalar value');

        }

        if (is_array($params)) {

            $params = array_values($params);

        } else {

            throw new Exception('Params must be given as array');

        }
        if ($this->notification) {

            $currentId = NULL;

        } else {

            $currentId = $this->id;

        }
       // 拼装成一个request请求

        $request = array(  'method' => $method,  'params' => $params,'id' => $currentId);

        $request = json_encode($request);

        $this->debug && $this->debug.='***** Request *****'."\n".$request."\n".'***** End Of request *****'."\n\n";

        $opts = array ('http' => array (

                                    'method'  => 'POST',

                                    'header'  => 'Content-type: application/json',

                                    'content' => $request

        ));

        //  关键几部

        $context  = stream_context_create($opts);

  if ( $result = file_get_contents($this->url, false, $context)) {

            $response = json_decode($result,true);

  } else {

   throw new Exception('Unable to connect to '.$this->url);

  }

        // 输出调试信息

        if ($this->debug) {

            echo nl2br(($this->debug));

        }

        // 检验response信息

        if (!$this->notification) {

            // check

            if ($response['id'] != $currentId) {

                throw new Exception('Incorrect response id (request id: '.$currentId.', response id: '.$response['id'].')');

            }

            if (!is_null($response['error'])) {

                throw new Exception('Request error: '.$response['error']);

            }

            return $response['result'];
        } else {

            return true;

        }

    }

}

?>

(三) 应用实例
(1)服务端 server.php

<?php

require_once 'jsonRPCServer.php';
// member 为测试类

require 'member.php';

// 服务端调用

$myExample = new member();

// 注入实例

jsonRPCServer::handle($myExample)

 or print 'no request';

?>

(2)测试类文件,member.php

class member{

    public function getName(){

        return 'hello word ' ;  // 返回字符串

    }

}

(3)客户端 client.php

require_once 'jsonRPCClient.php';
$url = 'http://localhost/rpc/server.php';

$myExample = new jsonRPCClient($url);
// 客户端调用

try {

 $name = $myExample->getName();

    echo $name ;

} catch (Exception $e) {

 echo nl2br($e->getMessage()).'<br />'."\n";

}
PHP 相关文章推荐
isset和empty的区别
Jan 15 PHP
mysql_fetch_assoc和mysql_fetch_row的功能加起来就是mysql_fetch_array
Jan 15 PHP
ThinkPHP3.1新特性之字段合法性检测详解
Jun 19 PHP
Eclipse的PHP插件PHPEclipse安装和使用
Jul 20 PHP
php集成环境xampp中apache无法启动问题解决方案
Nov 18 PHP
php传值赋值和传地址赋值用法实例分析
Jun 20 PHP
PHP导入导出Excel代码
Jul 07 PHP
PHP使用逆波兰式计算工资的方法
Jul 29 PHP
PHP内核探索:哈希表碰撞攻击原理
Jul 31 PHP
PHP实现微信商户支付企业付款到零钱功能
Sep 30 PHP
PHP时间戳和日期相互转换操作实例小结
Dec 18 PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 PHP
php实现读取内存顺序号
Mar 29 #PHP
php实现插入排序
Mar 29 #PHP
php实现插入数组但不影响原有顺序的方法
Mar 27 #PHP
WordPress自定义时间显示格式
Mar 27 #PHP
在php和MySql中计算时间差的方法详解
Mar 27 #PHP
PHP连接access数据库
Mar 27 #PHP
使用新浪微博API的OAuth认证发布微博实例
Mar 27 #PHP
You might like
模仿OSO的论坛(三)
2006/10/09 PHP
php下使用iconv需要注意的问题
2010/11/20 PHP
PHP+Ajax异步通讯实现用户名邮箱验证是否已注册( 2种方法实现)
2011/12/28 PHP
php代码书写习惯优化小结
2013/06/20 PHP
php的mail函数发送UTF-8编码中文邮件时标题乱码的解决办法
2015/10/20 PHP
PHP实现的二分查找算法实例分析
2017/12/19 PHP
jQuery 选择器项目实例分析及实现代码
2012/12/28 Javascript
浏览器页面区域大小的js获取方法
2013/09/21 Javascript
jQuery实现表格颜色交替显示的方法
2015/03/09 Javascript
微信小程序动态的加载数据实例代码
2017/04/14 Javascript
xmlplus组件设计系列之下拉刷新(PullRefresh)(6)
2017/05/03 Javascript
Bootstrap Table使用整理(一)
2017/06/09 Javascript
使用Node.js实现ORM的一种思路详解(图文)
2017/10/24 Javascript
Vue全家桶实践项目总结(推荐)
2017/11/04 Javascript
vue使用echarts实现水平柱形图实例
2020/09/09 Javascript
JQuery+drag.js上传图片并且实现图片拖曳
2020/11/18 jQuery
[01:23:59]2018DOTA2亚洲邀请赛 4.1 小组赛 B组 VP vs Secret
2018/04/03 DOTA
python切换hosts文件代码示例
2013/12/31 Python
Python的加密模块md5、sha、crypt使用实例
2014/09/28 Python
python实现登陆知乎获得个人收藏并保存为word文件
2015/03/16 Python
实例说明Python中比较运算符的使用
2015/05/13 Python
浅谈Python的条件判断语句if/else语句
2019/03/21 Python
在Python中过滤Windows文件名中的非法字符方法
2019/06/10 Python
python分数表示方式和写法
2019/06/26 Python
iphoneX 适配客户端H5页面的方法教程
2017/12/08 HTML / CSS
英国床垫在线:Mattress Online
2016/12/07 全球购物
服装厂厂长职责
2013/12/16 职场文书
会计专业毕业生自荐信范文
2013/12/20 职场文书
最新党员思想汇报
2014/01/01 职场文书
房地产销售计划书
2014/01/10 职场文书
自荐书范文范例
2014/02/13 职场文书
活动总结格式范文
2014/04/26 职场文书
国情备忘录观后感
2015/06/04 职场文书
幼儿园教师读书笔记
2015/06/29 职场文书
2016年学校十一国庆节活动总结
2016/04/01 职场文书
《水浒传》读后感3篇(范文)
2019/09/19 职场文书