正 文

PHP 远程过程调用 —— phprpc


www.7dspace.com  更新日期:2006-1-3 1:42:38  七度空间


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

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

下载: phprpc.php

   1. <?php
   2. /**
   3. * @author      Ma Bingyao(andot@ujn.edu.cn)
   4. * @copyright   2005 CoolCode.CN
   5. * @package     PHPRPC
   6. * @version     0.1
   7. * @link        http://www.coolcode.cn/?p=101
   8. *
   9. * Example usage:
  10. *
  11. * server.php
  12. * <?php
  13. * include('phprpc.php');
  14. * function add($a, $b) {
  15. *     return $a + $b;
  16. * }
  17. * function sub($a, $b) {
  18. *     return $a - $b;
  19. * }
  20. * new phprpc_server(array('add', 'sub'));
  21. * ?>
  22. *
  23. * client.php
  24. * <?php
  25. * include('phprpc.php');
  26. * $rpc_client = new phprpc_client('http://test.coolcode.cn/phprpc/server.php');
  27. * echo $rpc_client->add(1, 2);
  28. * echo "<br />";
  29. * echo $rpc_client->Sub(1, 2); // the function name is case-insensitive
  30. * echo "<br />";
  31. * // error handle
  32. * echo "<pre>";
  33. * $result = $rpc_client->mul(1, 2);  // no mul function
  34. * if (get_class($result) == "phprpc_error") {
  35. *     print_r($result);
  36. * }
  37. * $result = $rpc_client->add(1);    // wrong arguments
  38. * if (get_class($result) == "phprpc_error") {
  39. *     print_r($result);
  40. * }
  41. * $rpc_client->use_service('wrong url');  // wrong url
  42. * $result = $rpc_client->add(1, 2);
  43. * if (get_class($result) == "phprpc_error") {
  44. *     print_r($result);
  45. * }
  46. * echo "</pre>";
  47. * ?>
  48. */
  49. 
  50. class phprpc_error {
  51.     var $errno;
  52.     var $errstr;
  53.     function phprpc_error($errno, $errstr) {
  54.         $this->errno = $errno;
  55.         $this->errstr = $errstr;
  56.     }
  57. }
  58. 
  59. class phprpc_server {
  60.     function tolower(&$func, $keys) {
  61.         $func = strtolower($func);
  62.     }
  63.     function error_handler($errno, $errstr) {
  64.         echo $errno;
  65.         echo "\r\n\r\n";
  66.         echo $errstr;
  67.         exit;
  68.     }
  69.     function phprpc_server($functions) {
  70.         header("HTTP/1.1 200 OK");
  71.         header("Connection: close");
  72.         header("Content-Type: text/plain");
  73.         header("X-Powered-By: PHPRPC Server");
  74.         header("Date: " . gmdate("D, d M Y H:i:s") . " GMT");
  75.         error_reporting(0);
  76.         set_error_handler(array(&$this, 'error_handler'));
  77.         if (isset($_POST['phprpc_func'])) {
  78.             array_walk($functions, array(&$this, 'tolower'));
  79.             $function = strtolower(get_magic_quotes_gpc() ? stripslashes($_POST['phprpc_func']) : $_POST['phprpc_func']);
  80.             if (in_array($function, $functions)) {
  81.                 if (isset($_POST['phprpc_args'])) {
  82.                     $arguments = unserialize(base64_decode(get_magic_quotes_gpc() ? stripslashes($_POST['phprpc_args']) : $_POST['phprpc_args']));
  83.                 }
  84.                 else {
  85.                     $arguments = array();
  86.                 }
  87.                 $result = base64_encode(serialize(call_user_func_array($function, $arguments)));
  88.             }
  89.             else {
  90.                 $result = "1\r\n\r\nCan't find this function $function()";
  91.             }
  92.         }
  93.         else {
  94.             $result = "1\r\n\r\nCalled no function";
  95.         }
  96.         print $result;
  97.         restore_error_handler();
  98.     }
  99. }
 100. 
 101. class phprpc_client {
 102.     var $scheme;
 103.     var $host;
 104.     var $port;
 105.     var $path;
 106.     var $user;
 107.     var $pass;
 108.     var $timeout;
 109. 
 110.     function phprpc_client($url, $user = '', $pass = '', $timeout = 10) {
 111.         $this->use_service($url);
 112.         $this->user = $user;
 113.         $this->pass = $pass;
 114.         $this->timeout = $timeout;
 115.     }
 116. 
 117.     function use_service($url) {
 118.         $urlparts = parse_url($url);
 119. 
 120.         if (isset($urlparts['scheme']) && ($urlparts['scheme'] == "https")) {
 121.             $urlparts['scheme'] = "ssl";
 122.         }
 123.         else {
 124.             $urlparts['scheme'] = "";
 125.         }
 126. 
 127.         if (!isset($urlparts['host'])) {
 128.             if (isset($_SERVER["HTTP_HOST"])) {
 129.                 $urlparts['host'] = $_SERVER["HTTP_HOST"];
 130.             }
 131.             else if (isset($_SERVER["SERVER_NAME"])) {
 132.                 $urlparts['host'] = $_SERVER["SERVER_NAME"];
 133.             }
 134.             else {
 135.                 $urlparts['host'] = "localhost";
 136.             }
 137.         }
 138. 
 139.         if (!isset($urlparts['port'])) {
 140.             if ($urlparts['scheme'] == "ssl") {
 141.                 $urlparts['port'] = 443;
 142.             }
 143.             else {
 144.                 $urlparts['port'] = 80;
 145.             }
 146.         }
 147. 
 148.         if (!isset($urlparts['path'])) {
 149.             $urlparts['path'] = "/";
 150.         }
 151.         else if (($urlparts['path']{0} != '/') && ($_SERVER["PHP_SELF"]{0} == '/')) {
 152.             $urlparts['path'] = substr($_SERVER["PHP_SELF"], 0, strrpos($_SERVER["PHP_SELF"], '/') + 1) . $urlparts['path'];
 153.         }
 154. 
 155.         $this->scheme = $urlparts['scheme'];
 156.         $this->host = $urlparts['host'];
 157.         $this->port = $urlparts['port'];
 158.         $this->path = $urlparts['path'];
 159.     }
 160. 
 161.     function __invoke($function, $arguments) {
 162.         $request = "phprpc_func=$function";
 163.         if (count($arguments) > 0) {
 164.             $request .= "&phprpc_args=" . base64_encode(serialize($arguments));
 165.         }
 166.         $content_len = strlen($request);
 167.         $errno = 0;
 168.         $errstr = '';
 169.         $host = ($this->scheme) ? $this->scheme . "://" . $this->host : $this->host;
 170.         $handle = @fsockopen($host, $this->port, $errno, $errstr, $this->timeout);
 171.         $buf = '';
 172.         if ($handle) {
 173.             if ($this->user) {
 174.                 $auth = "Authorization: Basic " . base64_encode($this->user . ":" . $this->pass) . "\r\n";
 175.             }
 176.             $http_request =
 177.                 "POST $this->path HTTP/1.0\r\n" .
 178.                 "User-Agent: PHPRPC Client\r\n" .
 179.                 "Host: $this->host:$this->port\r\n" .
 180.                 $auth .
 181.                 "Content-Type: application/x-www-form-urlencoded\r\n" .
 182.                 "Content-Length: $content_len\r\n" .
 183.                 "\r\n" .
 184.                 $request;
 185.             fputs($handle, $http_request, strlen($http_request));
 186.             while (!feof($handle)) {
 187.                 $buf .= fgets($handle, 128);
 188.             }
 189.             fclose($handle);
 190.             if (strlen($buf)) {
 191.                 $buf = explode("\r\n\r\n", $buf);
 192.                 $header = $buf[0];
 193.                 if (strpos($header, 'X-Powered-By: PHPRPC Server') !== FALSE) {
 194.                     if (count($buf) == 2) {
 195.                         $result = unserialize(base64_decode($buf[1]));
 196.                     }
 197.                     else if (count($buf) == 3){
 198.                         $result = new phprpc_error((int)$buf[1], $buf[2]);
 199.                     }
 200.                     else {
 201.                         $result = new phprpc_error(E_ERROR, "Unknown error");
 202.                     }
 203.                 }
 204.                 else {
 205.                     $result = new phprpc_error(E_ERROR, "Wrong PHPRPC Server");
 206.                 }
 207.             }
 208.             else {
 209.                 $result = new phprpc_error(E_ERROR, "No data received from server");
 210.             }
 211.         }
 212.         else {
 213.             $result = new phprpc_error($errno, $errstr);
 214.         }
 215.         return $result;
 216.     }
 217. 
 218.     function __call($function, $arguments, &$return) {
 219.         $return = $this->__invoke($function, $arguments);
 220.         if (phpversion() < 5) return true;
 221.     }
 222. 
 223.     function call($function, $args) {
 224.         $arguments = func_get_args();
 225.         array_shift($arguments);
 226.         return $this->__invoke($function, $arguments);
 227.     }
 228. }
 229. 
 230. if (function_exists("overload") && version_compare(phpversion(), "5", "<")) {
 231.     overload('phprpc_client');
 232. }
 233. ?>


上一篇:利用z-index解决效果兼容
下一篇:浅析JDK 1.4“断言”
作者:andot  来源:CoolCode.CN ( 责任编辑:7dspace )
收藏此页】【打印】【关闭
站 内 搜 索
 

热 点 导 读
特 别 推 荐