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 *****"."".$request.""."***** End Of request *****".""; $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复制代码 代码如下:<?phprequire_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 />"."";}