当前位置: 首页 > 工具软件 > PHPRPC > 使用案例 >

php++rpc_PHP 远程过程调用 —— phprpc

司马高韵
2023-12-01

时候我们需要在两个 php 服务器之间执行远程过程调用,虽然用 xml-rpc 是一种解决方案,但是目前的 xml-rpc 的 php 实现用起来都非常麻烦,原来我也写过一个能够方便使用的 php 的 xml-rpc 类库, 但是那个需要安装 xmlrpc-epi 扩展,这对于不支持这个扩展的服务器就不方便了。所以我写了下面这个 phprpc 的类库,它没有使用 xml-rpc 协议,而是我自己定义的 phprpc 协议,这个虽然只能用于 php 程序之间的远程过程调用,但是使用起来比 xml-rpc 更方便。

其他语言也不是完全不可能实现,只是实现起来比用 php 麻烦点而已,因为这里对参数和返回值的序列化与反序列化直接使用的 php 的 serialize 和 unserialize,其他语言只要能够实现这两个函数,要实现这个协议也很简单。

下载:phprpc.php

<?php

/**

* @author Ma Bingyao(andot@ujn.edu.cn)

* @copyright 2005 CoolCode.CN

* @package PHPRPC

* @version 0.1

* @link http://www.coolcode.cn/?p=101

*

* Example usage:

*

* server.php

* <?php

* include('phprpc.php');

* function add($a, $b) {

* return $a + $b;

* }

* function sub($a, $b) {

* return $a - $b;

* }

* new phprpc_server(array('add', 'sub'));

* ?>

*

* client.php

* <?php

* include('phprpc.php');

* $rpc_client = new phprpc_client('http://test.coolcode.cn/phprpc/server.php');

* echo $rpc_client->add(1, 2);

* echo "
";

* echo $rpc_client->Sub(1, 2); // the function name is case-insensitive

* echo "
";

* // error handle

* echo "

";

* $result = $rpc_client->mul(1, 2); // no mul function

* if (get_class($result) == "phprpc_error") {

* print_r($result);

* }

* $result = $rpc_client->add(1); // wrong arguments

* if (get_class($result) == "phprpc_error") {

* print_r($result);

* }

* $rpc_client->use_service('wrong url'); // wrong url

* $result = $rpc_client->add(1, 2);

* if (get_class($result) == "phprpc_error") {

* print_r($result);

* }

* echo "

";

* ?>

*/

class phprpc_error {

var $errno;

var $errstr;

function phprpc_error($errno, $errstr) {

$this->errno = $errno;

$this->errstr = $errstr;

}

}

class phprpc_server {

function tolower(&$func, $keys) {

$func = strtolower($func);

}

function error_handler($errno, $errstr) {

echo $errno;

echo "\r\n\r\n";

echo $errstr;

exit;

}

function phprpc_server($functions) {

header("HTTP/1.1 200 OK");

header("Connection: close");

header("Content-Type: text/plain");

header("X-Powered-By: PHPRPC Server");

header("Date: " . gmdate("D, d M Y H:i:s") . " GMT");

error_reporting(0);

set_error_handler(array(&$this, 'error_handler'));

if (isset($_POST['phprpc_func'])) {

array_walk($functions, array(&$this, 'tolower'));

$function = strtolower(get_magic_quotes_gpc() ? stripslashes($_POST['phprpc_func']) : $_POST['phprpc_func']);

if (in_array($function, $functions)) {

if (isset($_POST['phprpc_args'])) {

$arguments = unserialize(base64_decode(get_magic_quotes_gpc() ? stripslashes($_POST['phprpc_args']) : $_POST['phprpc_args']));

}

else {

$arguments = array();

}

$result = base64_encode(serialize(call_user_func_array($function, $arguments)));

}

else {

$result = "1\r\n\r\nCan't find this function $function()";

}

}

else {

$result = "1\r\n\r\nCalled no function";

}

print $result;

restore_error_handler();

}

}

class phprpc_client {

var $scheme;

var $host;

var $port;

var $path;

var $user;

var $pass;

var $timeout;

function phprpc_client($url, $user = '', $pass = '', $timeout = 10) {

$this->use_service($url);

$this->user = $user;

$this->pass = $pass;

$this->timeout = $timeout;

}

function use_service($url) {

$urlparts = parse_url($url);

if (isset($urlparts['scheme']) && ($urlparts['scheme'] == "https")) {

$urlparts['scheme'] = "ssl";

}

else {

$urlparts['scheme'] = "";

}

if (!isset($urlparts['host'])) {

if (isset($_SERVER["HTTP_HOST"])) {

$urlparts['host'] = $_SERVER["HTTP_HOST"];

}

else if (isset($_SERVER["SERVER_NAME"])) {

$urlparts['host'] = $_SERVER["SERVER_NAME"];

}

else {

$urlparts['host'] = "localhost";

}

}

if (!isset($urlparts['port'])) {

if ($urlparts['scheme'] == "ssl") {

$urlparts['port'] = 443;

}

else {

$urlparts['port'] = 80;

}

}

if (!isset($urlparts['path'])) {

$urlparts['path'] = "/";

}

else if (($urlparts['path']{0} != '/') && ($_SERVER["PHP_SELF"]{0} == '/')) {

$urlparts['path'] = substr($_SERVER["PHP_SELF"], 0, strrpos($_SERVER["PHP_SELF"], '/') + 1) . $urlparts['path'];

}

$this->scheme = $urlparts['scheme'];

$this->host = $urlparts['host'];

$this->port = $urlparts['port'];

$this->path = $urlparts['path'];

}

function __invoke($function, $arguments) {

$request = "phprpc_func=$function";

if (count($arguments) > 0) {

$request .= "&phprpc_args=" . base64_encode(serialize($arguments));

}

$content_len = strlen($request);

$errno = 0;

$errstr = '';

$host = ($this->scheme) ? $this->scheme . "://" . $this->host : $this->host;

$handle = @fsockopen($host, $this->port, $errno, $errstr, $this->timeout);

$buf = '';

if ($handle) {

if ($this->user) {

$auth = "Authorization: Basic " . base64_encode($this->user . ":" . $this->pass) . "\r\n";

}

$http_request =

"POST $this->path HTTP/1.0\r\n" .

"User-Agent: PHPRPC Client\r\n" .

"Host: $this->host:$this->port\r\n" .

$auth .

"Content-Type: application/x-www-form-urlencoded\r\n" .

"Content-Length: $content_len\r\n" .

"\r\n" .

$request;

fputs($handle, $http_request, strlen($http_request));

while (!feof($handle)) {

$buf .= fgets($handle, 128);

}

fclose($handle);

if (strlen($buf)) {

$buf = explode("\r\n\r\n", $buf);

$header = $buf[0];

if (strpos($header, 'X-Powered-By: PHPRPC Server') !== FALSE) {

if (count($buf) == 2) {

$result = unserialize(base64_decode($buf[1]));

}

else if (count($buf) == 3){

$result = new phprpc_error((int)$buf[1], $buf[2]);

}

else {

$result = new phprpc_error(E_ERROR, "Unknown error");

}

}

else {

$result = new phprpc_error(E_ERROR, "Wrong PHPRPC Server");

}

}

else {

$result = new phprpc_error(E_ERROR, "No data received from server");

}

}

else {

$result = new phprpc_error($errno, $errstr);

}

return $result;

}

function __call($function, $arguments, &$return) {

$return = $this->__invoke($function, $arguments);

if (phpversion() < 5) return true;

}

function call($function, $args) {

$arguments = func_get_args();

array_shift($arguments);

return $this->__invoke($function, $arguments);

}

}

if (function_exists("overload") && version_compare(phpversion(), "5", "

overload('phprpc_client');

}

?>

PHP 远程过程调用 —— phprpc

 类似资料: