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读取30天之内的根据算法排序的代码
Apr 06 PHP
PHP 函数语法介绍一
Jun 14 PHP
php 图片上传类代码
Jul 17 PHP
PHP基础学习之流程控制的实现分析
Apr 28 PHP
yii框架builder、update、delete使用方法
Apr 30 PHP
smarty模板引擎之分配数据类型
Mar 30 PHP
分享自定义的几个PHP功能函数
Apr 15 PHP
php使用APC实现实时上传进度条功能
Oct 26 PHP
twig模板常用语句实例小结
Feb 04 PHP
PHP验证码无法显示的原因及解决办法
Aug 11 PHP
详解PHP中mb_strpos的使用
Feb 04 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 Calender(日历)代码分享
2014/01/03 PHP
PHP处理Json字符串解码返回NULL的解决方法
2014/09/01 PHP
PHP使用token防止表单重复提交的方法
2016/04/07 PHP
Aster vs KG BO3 第二场2.18
2021/03/10 DOTA
javascript下有关dom以及xml节点访问兼容问题
2007/11/26 Javascript
jquery 3D球状导航的文章分类
2010/07/06 Javascript
某页码显示的helper 少量调整,另附js版
2010/09/12 Javascript
js和as的稳定传值问题解决
2013/07/14 Javascript
HTML长文本截取含有HTML代码同样适用的两种方法
2013/07/31 Javascript
Hammer.js+轮播原理实现简洁的滑屏功能
2016/02/02 Javascript
javascript判断图片是否加载完成的方法推荐
2016/05/13 Javascript
浅谈javascript中的Function和Arguments
2016/08/30 Javascript
微信小程序 教程之注册程序
2016/10/17 Javascript
JavaScript学习笔记--常用的互动方法
2016/12/07 Javascript
jQuery实现的无缝广告图片左右滚动功能详解
2016/12/24 Javascript
webpack4 CSS Tree Shaking的使用
2018/09/03 Javascript
js中Function引用类型常见有用的方法和属性详解
2019/12/11 Javascript
vue实现用户长时间不操作自动退出登录功能的实现代码
2020/07/23 Javascript
[02:33]DOTA2亚洲邀请赛趣味视频之吐真话筒
2018/03/31 DOTA
Python自动扫雷实现方法
2015/07/25 Python
Python编程之微信推送模板消息功能示例
2017/08/21 Python
python爬虫基本知识
2018/03/05 Python
Python cookbook(数据结构与算法)将名称映射到序列元素中的方法
2018/03/22 Python
python ImageDraw类实现几何图形的绘制与文字的绘制
2020/02/26 Python
解决使用python print打印函数返回值多一个None的问题
2020/04/09 Python
使用opencv中匹配点对的坐标提取方式
2020/06/04 Python
HTML如何让IMG自动适应DIV容器大小的实现方法
2020/02/25 HTML / CSS
HTML5跳转小程序wx-open-launch-weapp的示例代码
2020/07/16 HTML / CSS
澳大利亚领先的在线礼品网站:Gifts Australia
2020/08/15 全球购物
高中生毕业自我鉴定范文
2013/12/22 职场文书
《维生素c的故事》教学反思
2014/02/18 职场文书
电子商务专业毕业生求职信
2014/06/12 职场文书
领导干部群众路线对照检查材料
2014/11/05 职场文书
承诺书的签字人,需不需要承担相应的责任?
2019/07/09 职场文书
spring注解 @PropertySource配置数据源全流程
2022/03/25 Java/Android
解决Vmware虚拟机安装centos8报错“Section %Packages Does Not End With %End. Pane Is Dead”
2022/06/01 Servers