php實(shí)現(xiàn)的一個(gè)簡(jiǎn)單json rpc框架實(shí)例
json rpc 是一種以json為消息格式的遠(yuǎn)程調(diào)用服務(wù),它是一套允許運(yùn)行在不同操作系統(tǒng)、不同環(huán)境的程序?qū)崿F(xiàn)基于Internet過(guò)程調(diào)用的規(guī)范和一系列的實(shí)現(xiàn)。這種遠(yuǎn)程過(guò)程調(diào)用可以使用http作為傳輸協(xié)議,也可以使用其它傳輸協(xié)議,傳輸?shù)膬?nèi)容是json消息體。
下面我們code一套基于php的rpc框架,此框架中包含rpc的服務(wù)端server,和應(yīng)用端client;
(一)PHP服務(wù)端RPCserver jsonRPCServer.php
class jsonRPCServer {
/**
*處理一個(gè)request類,這個(gè)類中綁定了一些請(qǐng)求參數(shù)
* @param object $object
* @return boolean
*/
public static function handle($object) {
// 判斷是否是一個(gè)rpc json請(qǐng)求
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);
// 執(zhí)行請(qǐng)求類中的接口
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;
// 請(qǐng)求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) {
// 檢驗(yàn)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;
}
// 拼裝成一個(gè)request請(qǐng)求
$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
));
// 關(guān)鍵幾部
$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);
}
// 輸出調(diào)試信息
if ($this->debug) {
echo nl2br(($this->debug));
}
// 檢驗(yàn)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;
}
}
}
?>
(三) 應(yīng)用實(shí)例
(1)服務(wù)端 server.php
<?php
require_once 'jsonRPCServer.php';
// member 為測(cè)試類
require 'member.php';
// 服務(wù)端調(diào)用
$myExample = new member();
// 注入實(shí)例
jsonRPCServer::handle($myExample)
or print 'no request';
?>
(2)測(cè)試類文件,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);
// 客戶端調(diào)用
try {
$name = $myExample->getName();
echo $name ;
} catch (Exception $e) {
echo nl2br($e->getMessage()).'<br />'."\n";
}
- 通過(guò) Redis 實(shí)現(xiàn) RPC 遠(yuǎn)程方法調(diào)用(支持多種編程語(yǔ)言)
- Python中實(shí)現(xiàn)遠(yuǎn)程調(diào)用(RPC、RMI)簡(jiǎn)單例子
- Java利用Sping框架編寫RPC遠(yuǎn)程過(guò)程調(diào)用服務(wù)的教程
- RPC、RMI、SOAP的區(qū)別詳解
- python使用rpc框架gRPC的方法
- 對(duì)python調(diào)用RPC接口的實(shí)例詳解
- Java實(shí)現(xiàn)簡(jiǎn)單的RPC框架的示例代碼
- 關(guān)于rpc長(zhǎng)連接與短連接的思考記錄
相關(guān)文章
php+mysqli使用面向?qū)ο蠓绞礁聰?shù)據(jù)庫(kù)實(shí)例
這篇文章主要介紹了php+mysqli使用面向?qū)ο蠓绞礁聰?shù)據(jù)庫(kù)的方法,實(shí)例分析了mysqli對(duì)象的創(chuàng)建、連接、更新及返回更新結(jié)果的技巧,需要的朋友可以參考下2015-01-01php中用foreach來(lái)操作數(shù)組的代碼
php中用foreach來(lái)操作數(shù)組的代碼,需要的朋友可以參考下。2011-07-07shell腳本作為保證PHP腳本不掛掉的守護(hù)進(jìn)程實(shí)例分享
以下是對(duì)用shell腳本作為保證PHP腳本不掛掉的守護(hù)進(jìn)程實(shí)例進(jìn)行了分析介紹,需要的朋友可以參考下2013-07-07PHP常用函數(shù)和常見(jiàn)疑難問(wèn)題解答
雖然PHP在整體功能上不如Java強(qiáng)大,但相比PHP而言Java算是較重量級(jí)的,所以在小中型系統(tǒng)的開(kāi)發(fā)上,使用PHP的趨勢(shì)不可擋,就算是大型網(wǎng)站,比如淘寶也部分使用了PHP(Java后臺(tái)邏輯+PHP前臺(tái)展示),所以趕緊開(kāi)始學(xué)PHP啦2014-03-03php實(shí)現(xiàn)表單多按鈕提交action的處理方法
這篇文章主要介紹了php實(shí)現(xiàn)表單多按鈕提交action的處理方法,需要的朋友可以參考下2015-10-10PHP實(shí)現(xiàn)創(chuàng)建微信自定義菜單的方法示例
這篇文章主要介紹了PHP實(shí)現(xiàn)創(chuàng)建微信自定義菜單的方法,結(jié)合實(shí)例形式分析了php創(chuàng)建微信自定義菜單的原理、步驟與具體實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-07-07