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中基本符号及使用方法
Mar 23 PHP
让PHP支持断点续传的源码
May 16 PHP
允许phpmyadmin空密码登录的配置方法
May 29 PHP
PHP获取数组中某元素的位置及array_keys函数应用
Jan 29 PHP
PHP把空格、换行符、中文逗号等替换成英文逗号的正则表达式
May 04 PHP
ThinkPHP CURD方法之data方法详解
Jun 18 PHP
ThinkPHP控制器里javascript代码不能执行的解决方法
Nov 22 PHP
php支付宝接口用法分析
Jan 04 PHP
2款PHP无限级分类实例代码
Nov 11 PHP
phpcms的分类名称和类别名称的调用
Jan 05 PHP
PHP开发之归档格式phar文件概念与用法详解【创建,使用,解包还原提取】
Nov 17 PHP
php实现推荐功能的简单实例
Sep 29 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过滤危险html代码的函数
2008/07/22 PHP
防止MySQL注入或HTML表单滥用的PHP程序
2009/01/21 PHP
分享一段PHP制作的中文拼音首字母工具类
2014/12/11 PHP
php利用事务处理转账问题
2015/04/22 PHP
Ajax+PHP实现的模拟进度条功能示例
2019/02/11 PHP
基于JQuery的Pager分页器实现代码
2010/07/17 Javascript
取得元素的左和上偏移量的方法
2014/09/17 Javascript
node.js中的http.response.removeHeader方法使用说明
2014/12/14 Javascript
使用jQuery不判断浏览器高度解决iframe自适应高度问题
2014/12/16 Javascript
jQuery中:first选择器用法实例
2014/12/30 Javascript
JavaScript中Cookie操作实例
2015/01/09 Javascript
jQuery+css3实现文字跟随鼠标的上下抖动
2015/07/31 Javascript
JS日程管理插件FullCalendar中文说明文档
2017/02/06 Javascript
Vue keepAlive 数据缓存工具实现返回上一个页面浏览的位置
2019/05/10 Javascript
jQuery zTree插件使用简单教程
2019/08/16 jQuery
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
2020/07/30 Javascript
python实现文件名批量替换和内容替换
2014/03/20 Python
Python模块搜索概念介绍及模块安装方法介绍
2015/06/03 Python
使用C#配合ArcGIS Engine进行地理信息系统开发
2016/02/19 Python
Python 爬虫学习笔记之正则表达式
2016/09/21 Python
Python递归函数定义与用法示例
2017/06/02 Python
实例详解Python装饰器与闭包
2019/07/29 Python
通过实例学习Python Excel操作
2020/01/06 Python
在 Python 中接管键盘中断信号的实现方法
2020/02/04 Python
tensorflow与numpy的版本兼容性问题的解决
2021/01/08 Python
python 利用matplotlib在3D空间中绘制平面的案例
2021/02/06 Python
利用HTML5绘制点线面组成的3D图形的示例
2015/05/12 HTML / CSS
澳大利亚先进的皮肤和激光诊所购物网站:Soho Skincare
2018/10/15 全球购物
Public Desire美国/加拿大:全球性的在线鞋类品牌
2018/12/17 全球购物
Luxplus荷兰:以会员价购买美容产品等,独家优惠
2019/08/30 全球购物
如何减少垃圾回收让内存更加有效使用
2013/10/18 面试题
2014年秋季新学期寄语
2014/08/02 职场文书
2014年大学生村官工作总结
2014/11/19 职场文书
导游词之无锡梅园
2019/11/28 职场文书
fastdfs+nginx集群搭建的实现
2021/03/31 Servers
vue如何在data中引入图片的正确路径
2022/06/05 Vue.js