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


Posted in PHP onFebruary 23, 2020

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

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

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

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

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

RpcServer.php代码如下:

<?php
class RpcServer {
  protected $serv = null;

  public function __construct($host, $port, $path) {
    //创建一个tcp socket服务
    $this->serv = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr);
    if (!$this->serv) {
      exit("{$errno} : {$errstr} \n");
    }
    //判断我们的RPC服务目录是否存在
    $realPath = realpath(__DIR__ . $path);
    if ($realPath === false || !file_exists($realPath)) {
      exit("{$path} error \n");
    }

    while (true) {
      $client = stream_socket_accept($this->serv);

      if ($client) {
        //这里为了简单,我们一次性读取
        $buf = fread($client, 2048);
        //解析客户端发送过来的协议
        $classRet = preg_match('/Rpc-Class:\s(.*);\r\n/i', $buf, $class);
        $methodRet = preg_match('/Rpc-Method:\s(.*);\r\n/i', $buf, $method);
        $paramsRet = preg_match('/Rpc-Params:\s(.*);\r\n/i', $buf, $params);
        
        if($classRet && $methodRet) {
          $class = ucfirst($class[1]);
          $file = $realPath . '/' . $class . '.php';
          //判断文件是否存在,如果有,则引入文件
          if(file_exists($file)) {
            require_once $file;
            //实例化类,并调用客户端指定的方法
            $obj = new $class();
            //如果有参数,则传入指定参数
            if(!$paramsRet) {
              $data = $obj->$method[1]();
            } else {
              $data = $obj->$method[1](json_decode($params[1], true));
            }
            //把运行后的结果返回给客户端
            fwrite($client, $data);
          }
        } else {
          fwrite($client, 'class or method error');
        }
        //关闭客户端
        fclose($client);
      }
    }
  }

  public function __destruct() {
    fclose($this->serv);
  }
}

new RpcServer('127.0.0.1', 8888, './service');

RpcClient.php代码如下:

<?php

class RpcClient {
  protected $urlInfo = array();
  
  public function __construct($url) {
    //解析URL
    $this->urlInfo = parse_url($url);
    if(!$this->urlInfo) {
      exit("{$url} error \n");
    }
  }
  
  public function __call($method, $params) {
    //创建一个客户端
    $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
    if (!$client) {
      exit("{$errno} : {$errstr} \n");
    }
    //传递调用的类名
    $class = basename($this->urlInfo['path']);
    $proto = "Rpc-Class: {$class};" . PHP_EOL;
    //传递调用的方法名
    $proto .= "Rpc-Method: {$method};" . PHP_EOL;
    //传递方法的参数
    $params = json_encode($params);
    $proto .= "Rpc-Params: {$params};" . PHP_EOL;
    //向服务端发送我们自定义的协议数据
    fwrite($client, $proto);
    //读取服务端传来的数据
    $data = fread($client, 2048);
    //关闭客户端
    fclose($client);
    return $data;
  }
}

$cli = new RpcClient('http://127.0.0.1:8888/test');
echo $cli->hehe();
echo $cli->hehe2(array('name' => 'test', 'age' => 27));

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

> php RpcServer.php
> php RpcClient.php

结果如下:

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

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

Test.php代码如下:

<?php
class Test {
  public function hehe() {
    return 'hehe';
  }
  public function hehe2($params) {
    return json_encode($params);
  }
}

目录结构如下:

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

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

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

希望本文所述对大家PHP程序设计有所帮助。

PHP 相关文章推荐
php分页函数
Jul 08 PHP
PHP 已经成熟
Dec 04 PHP
PHP 远程关机实现代码
Nov 10 PHP
PHP的SQL注入实现(测试代码安全不错)
Feb 27 PHP
php中CI操作多个数据库的代码
Jul 05 PHP
php利用事务处理转账问题
Apr 22 PHP
简单谈谈favicon
Jun 10 PHP
谈谈PHP中substr和substring的正确用法及相关参数的介绍
Dec 16 PHP
php实现简单爬虫的开发
Mar 28 PHP
Thinkphp框架中D方法与M方法的区别
Dec 23 PHP
Yii框架Session与Cookie使用方法示例
Oct 14 PHP
PHP设计模式之数据访问对象模式(DAO)原理与用法实例分析
Dec 12 PHP
php 使用ActiveMQ发送消息,与处理消息操作示例
Feb 23 #PHP
php实现通过stomp协议连接ActiveMQ操作示例
Feb 23 #PHP
php ActiveMQ的安装与使用方法图文教程
Feb 23 #PHP
php 多进程编程父进程的阻塞与非阻塞实例分析
Feb 22 #PHP
php7 图形用户界面GUI 开发示例
Feb 22 #PHP
PHP Beanstalkd消息队列的安装与使用方法实例详解
Feb 21 #PHP
PHP pthreads v3在centos7平台下的安装与配置操作方法
Feb 21 #PHP
You might like
用ODBC的分页显示
2006/10/09 PHP
小文件php+SQLite存储方案
2010/09/04 PHP
PHP计算近1年的所有月份
2017/03/13 PHP
Symfony2针对输入时间进行查询的方法分析
2017/06/28 PHP
JavaScript作用域链示例分享
2014/05/27 Javascript
javascript使用正则控制input输入框允许输入的值方法大全
2014/06/19 Javascript
JQuery 实现在同一页面锚点链接之间的平滑滚动
2014/10/29 Javascript
jQuery实现“扫码阅读”功能
2015/01/21 Javascript
javascript结合fileReader 实现上传图片
2015/01/30 Javascript
javascript如何操作HTML下拉列表标签
2015/08/20 Javascript
JavaScript学习笔记之ES6数组方法
2016/03/25 Javascript
js 中获取制定的cook信息实现方法
2016/11/19 Javascript
js判断一个字符串是以某个字符串开头的简单实例
2016/12/27 Javascript
详解通过JSON数据使用VUE.JS
2017/05/26 Javascript
微信小程序开发教程之增加mixin扩展
2017/08/09 Javascript
对vue中methods互相调用的方法详解
2018/08/30 Javascript
angular4中*ngFor不能对返回来的对象进行循环的解决方法
2018/09/12 Javascript
JS实现将对象转化为数组的方法分析
2019/01/21 Javascript
python通过colorama模块在控制台输出彩色文字的方法
2015/03/19 Python
使用pdb模块调试Python程序实例
2015/06/02 Python
梯度下降法介绍及利用Python实现的方法示例
2017/07/12 Python
python实现zabbix发送短信脚本
2018/09/17 Python
python实现创建新列表和新字典,并使元素及键值对全部变成小写
2019/01/15 Python
python 利用pandas将arff文件转csv文件的方法
2019/02/12 Python
python 实现创建文件夹和创建日志文件的方法
2019/07/07 Python
浅谈Keras参数 input_shape、input_dim和input_length用法
2020/06/29 Python
python实现视频压缩功能
2020/12/18 Python
编写用C语言实现的求n阶阶乘问题的递归算法
2014/10/21 面试题
某公司面试题
2012/03/05 面试题
DELPHI中如何调用API,可举例说明
2014/01/16 面试题
小学教育毕业生自荐信
2013/11/18 职场文书
试用期转正鉴定评语
2014/01/27 职场文书
领导班子四风表现材料
2014/08/23 职场文书
党员教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
团队拓展训练感想
2015/08/07 职场文书
react使用antd的上传组件实现文件表单一起提交功能(完整代码)
2021/06/29 Javascript