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之第九天
Oct 09 PHP
PHP个人网站架设连环讲(一)
Oct 09 PHP
Uchome1.2 1.5 代码学习 common.php
Apr 24 PHP
PHP为表单获取的URL 地址预设 http 字符串函数代码
May 26 PHP
保存到桌面、设为桌面且带图标的PHP代码
Nov 19 PHP
PHP中抽象类、接口的区别与选择分析
Mar 29 PHP
详谈php静态方法及普通方法的区别
Oct 04 PHP
几行代码轻松实现PHP文件打包下载zip
Mar 01 PHP
PHP实现添加购物车功能
Mar 06 PHP
解决php 处理 form 表单提交多个 name 属性值相同的 input 标签问题
May 11 PHP
php 生成加密公钥加密私钥实例详解
Jun 16 PHP
Thinkphp5.0 框架实现控制器向视图view赋值及视图view取值操作示例
Oct 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
福利彩票幸运号码自动生成器
2006/10/09 PHP
php 图片上添加透明度渐变的效果
2009/06/29 PHP
PHP垃圾回收机制简单说明
2010/07/22 PHP
thinkphp框架下404页面设置 仅三步
2016/05/14 PHP
PHP耦合设计模式实例分析
2018/08/08 PHP
php实现微信公众号创建自定义菜单功能的实例代码
2019/06/11 PHP
PHP 实现文件压缩解压操作的方法
2019/06/14 PHP
tp5框架前台无限极导航菜单类实现方法分析
2020/03/29 PHP
jquery和ajax的关系详细介绍
2013/11/29 Javascript
jquery中获得元素尺寸和坐标的方法整理
2014/05/18 Javascript
深入了解Node.js中的一些特性
2014/09/25 Javascript
JavaScript开发人员的10个关键习惯小结
2014/12/05 Javascript
JQuery+CSS实现图片上放置按钮的方法
2015/05/29 Javascript
简介JavaScript中的italics()方法的使用
2015/06/08 Javascript
jquery if条件语句的写法
2016/05/19 Javascript
js中获取键盘按下键值event.keyCode、event.charCode和event.which的兼容性详解
2017/03/15 Javascript
Vue+ElementUI实现表单动态渲染、可视化配置的方法
2018/03/07 Javascript
新版小程序登录授权的方法
2018/12/12 Javascript
Vue 3.0双向绑定原理的实现方法
2019/10/23 Javascript
Vue简单实现原理详解
2020/05/07 Javascript
js实现购物车商品数量加减
2020/09/21 Javascript
详解Python迭代和迭代器
2016/03/28 Python
Python入门之三角函数atan2()函数详解
2017/11/08 Python
Python列表推导式与生成器表达式用法示例
2018/02/08 Python
pygame实现简易飞机大战
2018/09/11 Python
python GUI库图形界面开发之PyQt5状态栏控件QStatusBar详细使用方法实例
2020/02/28 Python
pycharm进入时每次都是insert模式的解决方式
2021/02/05 Python
日本最新流行服饰网购:Nissen
2016/07/24 全球购物
《中彩那天》教学反思
2014/02/22 职场文书
大学生就业自我推荐信
2014/05/10 职场文书
触电现场处置方案
2014/05/14 职场文书
数据保密承诺书
2014/06/03 职场文书
庆六一文艺汇演活动方案
2014/08/26 职场文书
企业爱心捐款倡议书
2015/04/27 职场文书
springboot集成springCloud中gateway时启动报错的解决
2021/07/16 Java/Android
MyBatis-Plus 批量插入数据的操作方法
2021/09/25 Java/Android