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

  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";

  }