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写的小东西
Dec 06 PHP
PHP 异步执行方法,模拟多线程的应用分析
Jun 03 PHP
php中如何同时使用session和cookie来保存用户登录信息
Jul 05 PHP
解决php接收shell返回的结果中文乱码问题
Jan 23 PHP
php判断正常访问和外部访问的示例
Feb 10 PHP
ThinkPHP无限级分类原理实现留言与回复功能实例
Oct 31 PHP
PHP设置进度条的方法
Jul 08 PHP
php实现可运算的验证码
Nov 10 PHP
php正则表达式基本知识与应用详解【经典教程】
Apr 17 PHP
PHP利用Cookie设置用户30分钟未操作自动退出功能
Jul 03 PHP
thinkPHP3.2.3实现阿里大于短信验证的方法
Jun 06 PHP
浅谈laravel中的关联查询with的问题
Oct 10 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
关于php curl获取301或302转向的网址问题的解决方法
2011/06/02 PHP
thinkphp实现上一篇与下一篇的方法
2014/12/08 PHP
PHP Echo字符串的连接格式
2016/03/07 PHP
PHP Filter过滤器全面解析
2016/08/09 PHP
Yii 框架使用Forms操作详解
2020/05/18 PHP
jquery自动完成插件(autocomplete)应用之PHP版
2009/12/15 Javascript
JavaScript 函数惰性载入的实现及其优点介绍
2013/08/12 Javascript
JQuery中对Select的option项的添加、删除、取值
2013/08/25 Javascript
JavaScript类型系统之正则表达式
2016/01/05 Javascript
javascript显示上周、上个月日期的处理方法
2016/02/03 Javascript
js将滚动条滚动到指定位置的简单实现方法
2016/06/25 Javascript
JavaScript作用域示例详解
2016/07/07 Javascript
通过示例彻底搞懂js闭包
2017/08/10 Javascript
vue.js项目打包上线的图文教程
2017/11/16 Javascript
JS装饰器函数用法总结
2018/04/21 Javascript
JavaScript中常见内置函数用法示例
2018/05/14 Javascript
Vue项目History模式404问题解决方法
2018/10/31 Javascript
详解webpack引入第三方库的方式以及注意事项
2019/01/15 Javascript
JS基于开关思想实现的数组去重功能【案例】
2019/02/18 Javascript
详解小程序用户登录状态检查与更新实例
2019/05/15 Javascript
js实现拾色器插件(ColorPicker)
2020/05/21 Javascript
Vue开发中常见的套路和技巧总结
2020/11/24 Vue.js
Python易忽视知识点小结
2015/05/25 Python
人生苦短我用python python如何快速入门?
2018/03/12 Python
13个Pandas实用技巧,助你提高开发效率
2020/08/19 Python
利用Python实现Json序列化库的方法步骤
2020/09/09 Python
Python爬虫+Tkinter制作一个翻译软件的示例
2021/02/20 Python
Nike台湾官方商店:Nike.com (TW)
2017/08/16 全球购物
师范应届生语文教师求职信
2013/10/29 职场文书
大学生毕业的自我鉴定
2013/11/13 职场文书
骨干教师培训制度
2014/01/13 职场文书
什么是就业协议书
2014/04/17 职场文书
初中优秀学生评语
2014/12/29 职场文书
2015年社区党建工作汇报材料
2015/06/25 职场文书
html实现弹窗的实例
2021/06/09 HTML / CSS
React四级菜单的实现
2022/04/08 Javascript