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 相关文章推荐
真正面向对象编程:PHP5.01发布
Oct 09 PHP
PHP数组 为文章加关键字连接 文章内容自动加链接
Dec 29 PHP
php在项目中寻找代码的坏味道(综艺命名)
Jul 19 PHP
PHP 获取文件权限函数介绍
Jul 11 PHP
Yii中CGridView关联表搜索排序方法实例详解
Dec 03 PHP
php网页病毒清除类
Dec 08 PHP
PHP的伪随机数与真随机数详解
May 27 PHP
php通过排列组合实现1到9数字相加都等于20的方法
Aug 03 PHP
php微信开发之批量生成带参数的二维码
Jun 26 PHP
浅谈PHP中的错误处理和异常处理
Feb 04 PHP
PHP简单计算两个时间差的方法示例
Jun 20 PHP
laravel5.5安装jwt-auth 生成token令牌的示例
Oct 24 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
php中{}大括号是什么意思
2013/12/01 PHP
PHP针对常规模板引擎中与CSS/JSON冲突的解决方法
2014/08/19 PHP
PHP实现无限级分类(不使用递归)
2015/10/22 PHP
通过Mootools 1.2来操纵HTML DOM元素
2009/09/15 Javascript
jQuery.clean使用方法及思路分析
2013/01/07 Javascript
js如何取消事件冒泡
2013/09/23 Javascript
兼容主流浏览器的iframe自适应高度js脚本
2014/01/10 Javascript
js控制href内容的连接内容的变化示例
2014/04/30 Javascript
js取模(求余数)隔行变色
2014/05/15 Javascript
jquery UI Datepicker时间控件的使用方法(加强版)
2015/11/07 Javascript
整理Javascript流程控制语句学习笔记
2015/11/29 Javascript
javascript函数命名的三种方式及区别介绍
2016/03/22 Javascript
14 个折磨人的 JavaScript 面试题
2016/08/08 Javascript
JS前端笔试题分析
2016/12/19 Javascript
js模拟支付宝密码输入框
2017/04/11 Javascript
微信小程序movable view移动图片和双指缩放实例代码
2017/08/08 Javascript
移动端网页开发调试神器Eruda的介绍与使用技巧
2017/10/30 Javascript
JS实现的找零张数最小问题示例
2017/11/28 Javascript
vue解决一个方法同时发送多个请求的问题
2018/09/25 Javascript
Jquery的Ajax技术使用方法
2019/01/21 jQuery
Android 自定义view仿微信相机单击拍照长按录视频按钮
2019/07/19 Javascript
highcharts.js数据绑定方式代码实例
2019/11/13 Javascript
在DigitalOcean的服务器上部署flaskblog应用
2015/12/19 Python
Python插件virtualenv搭建虚拟环境
2017/11/20 Python
详解python项目实战:模拟登陆CSDN
2019/04/04 Python
详解使用PyInstaller将Pygame库编写的小游戏程序打包为exe文件
2019/08/23 Python
Python基于Serializer实现字段验证及序列化
2020/11/04 Python
css3实现图片遮罩效果鼠标hover以后出现文字
2013/11/05 HTML / CSS
全面解析HTML5中的标准属性与自定义属性
2016/02/18 HTML / CSS
深入浅析HTML5中的article和section的区别
2018/05/15 HTML / CSS
服务行业个人求职的自我评价
2013/12/12 职场文书
银行存款证明样本
2014/01/17 职场文书
参观接待方案
2014/03/17 职场文书
2014年创先争优活动总结
2014/05/04 职场文书
核心价值观演讲稿
2014/05/13 职场文书
世界遗产导游词
2015/02/13 职场文书