当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP实现创建一个RPC服务操作示例

发布:smiling 来源: PHP粉丝网  添加日期:2022-02-14 12:40:04 浏览: 评论:0 

本文实例讲述了PHP实现创建一个RPC服务操作,分享给大家供大家参考,具体如下:

RPC全称为Remote Procedure Call,翻译过来为"远程过程调用"。主要应用于不同的系统之间的远程通信和相互调用。

比如有两个系统,一个是PHP写的,一个是JAVA写的,而PHP想要调用JAVA中的某个类的某个方法,这时候就需要用到RPC了。

怎么调?直接调是不可能,只能是PHP通过某种自定义协议请求JAVA的服务,JAVA解析该协议,在本地实例化类并调用方法,然后把结果返回给PHP。

这里我们用PHP的socket扩展来创建一个服务端和客户端,演示调用过程。

RpcServer.php代码如下:

  1. <?php 
  2. class RpcServer { 
  3.   protected $serv = null; 
  4.  
  5.   public function __construct($host$port$path) { 
  6.     //创建一个tcp socket服务 
  7.     $this->serv = stream_socket_server("tcp://{$host}:{$port}"$errno$errstr); 
  8.     if (!$this->serv) { 
  9.       exit("{$errno} : {$errstr} \n"); 
  10.     } 
  11.     //判断我们的RPC服务目录是否存在 
  12.     $realPath = realpath(__DIR__ . $path); 
  13.     if ($realPath === false || !file_exists($realPath)) { 
  14.       exit("{$path} error \n"); 
  15.     } 
  16.  
  17.     while (true) { 
  18.       $client = stream_socket_accept($this->serv); 
  19.  
  20.       if ($client) { 
  21.         //这里为了简单,我们一次性读取 
  22.         $buf = fread($client, 2048); 
  23.         //解析客户端发送过来的协议 
  24.         $classRet = preg_match('/Rpc-Class:\s(.*);\r\n/i'$buf$class); 
  25.         $methodRet = preg_match('/Rpc-Method:\s(.*);\r\n/i'$buf$method); 
  26.         $paramsRet = preg_match('/Rpc-Params:\s(.*);\r\n/i'$buf$params); 
  27.           
  28.         if($classRet && $methodRet) { 
  29.           $class = ucfirst($class[1]); 
  30.           $file = $realPath . '/' . $class . '.php'
  31.           //判断文件是否存在,如果有,则引入文件 
  32.           if(file_exists($file)) { 
  33.             require_once $file
  34.             //实例化类,并调用客户端指定的方法 
  35.             $obj = new $class(); 
  36.             //如果有参数,则传入指定参数 
  37.             if(!$paramsRet) { 
  38.               $data = $obj->$method[1](); 
  39.             } else { 
  40.               $data = $obj->$method[1](json_decode($params[1], true)); 
  41.             } 
  42.             //把运行后的结果返回给客户端 
  43.             fwrite($client$data); 
  44.           } 
  45.         } else { 
  46.           fwrite($client'class or method error'); 
  47.         } 
  48.         //关闭客户端 
  49.         fclose($client); 
  50.       } 
  51.     } 
  52.   } 
  53.  
  54.   public function __destruct() { 
  55.     fclose($this->serv); 
  56.   } 
  57.  
  58. new RpcServer('127.0.0.1', 8888, './service'); 

RpcClient.php代码如下:

  1. <?php 
  2.  
  3. class RpcClient { 
  4.   protected $urlInfo = array(); 
  5.     
  6.   public function __construct($url) { 
  7.     //解析URL 
  8.     $this->urlInfo = parse_url($url); 
  9.     if(!$this->urlInfo) { 
  10.       exit("{$url} error \n"); 
  11.     } 
  12.   } 
  13.     
  14.   public function __call($method$params) { 
  15.     //创建一个客户端 
  16.     $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}"$errno$errstr); 
  17.     if (!$client) { 
  18.       exit("{$errno} : {$errstr} \n"); 
  19.     } 
  20.     //传递调用的类名 
  21.     $class = basename($this->urlInfo['path']); 
  22.     $proto = "Rpc-Class: {$class};" . PHP_EOL; 
  23.     //传递调用的方法名 
  24.     $proto .= "Rpc-Method: {$method};" . PHP_EOL; 
  25.     //传递方法的参数 
  26.     $params = json_encode($params); 
  27.     $proto .= "Rpc-Params: {$params};" . PHP_EOL; 
  28.     //向服务端发送我们自定义的协议数据 
  29.     fwrite($client$proto); 
  30.     //读取服务端传来的数据 
  31.     $data = fread($client, 2048); 
  32.     //关闭客户端 
  33.     fclose($client); 
  34.     return $data
  35.   } 
  36.  
  37. $cli = new RpcClient('http://127.0.0.1:8888/test'); 
  38. echo $cli->hehe(); 
  39. echo $cli->hehe2(array('name' => 'test''age' => 27)); 

然后分别运行上面两个脚本(注意,php要添加环境变量)

> php RpcServer.php

> php RpcClient.php

结果如下:

PHP实现创建一个RPC服务操作示例

Test.php代码如下:

  1. <?php 
  2. class Test { 
  3.   public function hehe() { 
  4.     return 'hehe'
  5.   } 
  6.   public function hehe2($params) { 
  7.     return json_encode($params); 
  8.   } 

目录结构如下:

PHP实现创建一个RPC服务操作示例

上面我们自定义的协议,可以随意修改,只要是客户端和服务端两边能够统一并能解析。

客户端通过请求服务端,把要调用的类,方法和参数传递给服务端,服务端去通过实例化调用方法返回结果。

Tags: RPC服务操作

分享到: