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中通过ADO调用Asscess数据库和COM程序
Oct 09 PHP
php 文件上传系统手记
Oct 26 PHP
php Session存储到Redis的方法
Nov 04 PHP
php防止SQL注入详解及防范
Nov 12 PHP
PHP实现的博客欢迎提示功能(很特别哦)
Jun 05 PHP
php操作XML、读取数据和写入数据的实现代码
Aug 15 PHP
thinkphp中memcache的用法实例
Nov 29 PHP
php替换字符串中间字符为省略号的方法
May 04 PHP
php结合正则获取字符串中数字
Jun 19 PHP
phpStudy 2016 使用教程详解(支持PHP7)
Oct 18 PHP
php文件上传原理与实现方法详解
Dec 20 PHP
Laravel框架使用技巧之使用url()全局函数返回前一个页面的地址方法详解
Apr 06 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
最省空间的计数器
2006/10/09 PHP
php文件读取方法实例分析
2015/06/20 PHP
详解关于php的xdebug配置(编辑器vscode)
2019/01/29 PHP
动态调用css文件——jquery的应用
2007/02/20 Javascript
javascript据option的value值快速设定初始的selected选项
2007/08/13 Javascript
文档对象模型DOM通俗讲解
2013/11/01 Javascript
html的DOM中Event对象onblur事件用法实例
2015/01/21 Javascript
jQuery源码分析之Callbacks详解
2015/03/13 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
2015/04/03 Javascript
原生javascript实现匀速运动动画效果
2016/02/26 Javascript
js操作DOM--添加、删除节点的简单实例
2016/07/08 Javascript
IE下JS保存图片的简单实例
2016/07/15 Javascript
AngularJS中的API(接口)简单实现
2016/07/28 Javascript
基于slideout.js实现移动端侧边栏滑动特效
2016/11/28 Javascript
NodeJS实现客户端js加密
2017/01/09 NodeJs
Easyui Tree获取当前选择节点的所有顶级父节点
2017/02/14 Javascript
微信小程序数据统计和错误统计的实现方法
2019/06/26 Javascript
解决echarts 一条柱状图显示两个值,类似进度条的问题
2020/07/20 Javascript
vue实现移动端返回顶部
2020/10/12 Javascript
python实现的正则表达式功能入门教程【经典】
2017/06/05 Python
Python图像处理之简单画板实现方法示例
2018/08/30 Python
django将网络中的图片,保存成model中的ImageField的实例
2019/08/07 Python
Python Des加密解密如何实现软件注册码机器码
2020/01/08 Python
Python如何将字符串转换为日期
2020/07/31 Python
calendar在python3时间中常用函数举例详解
2020/11/18 Python
html5配合css3实现带提示文字的输入框(摆脱js)
2013/03/08 HTML / CSS
amazeui页面校验功能的实现代码
2020/08/24 HTML / CSS
汽车维修与检测专业应届生求职信
2013/11/12 职场文书
高二美术教学反思
2014/01/14 职场文书
材料加工工程求职信
2014/02/19 职场文书
青春飞扬演讲稿
2014/09/11 职场文书
贷款担保书
2015/01/20 职场文书
仓管员岗位职责
2015/02/03 职场文书
B站评分公认最好看的动漫,你的名字评分9.9,第六备受喜欢
2022/03/18 日漫
日本十大血腥动漫,那些被禁播的动漫盘点
2022/03/21 日漫
vue3不同环境下实现配置代理
2022/05/25 Vue.js