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 Zip压缩 在线对文件进行压缩的函数
May 26 PHP
php摘要生成函数(无乱码)
Feb 04 PHP
php eval函数用法 PHP中eval()函数小技巧
Oct 31 PHP
php计算两个坐标(经度,纬度)之间距离的方法
Apr 17 PHP
php数组比较实现查找连续数的方法
Jul 29 PHP
PHP执行SQL文件并将SQL文件导入到数据库
Sep 17 PHP
PHP中配置IIS7实现基本身份验证的方法
Sep 24 PHP
laravel5创建service provider和facade的方法详解
Jul 26 PHP
PHP 二维关联数组根据其中一个字段排序(推荐)
Apr 04 PHP
PHP中error_reporting函数用法详细介绍
Jun 11 PHP
使用PHP+Redis实现延迟任务,实现自动取消订单功能
Nov 21 PHP
php的无刷新操作实现方法分析
Feb 28 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分多步骤填写发布信息的简单方法实例代码
2012/09/23 PHP
php中header设置常见文件类型的content-type
2015/06/23 PHP
Laravel自定义 封装便捷返回Json数据格式的引用方法
2019/09/29 PHP
解决表单中第一个非隐藏的元素获得焦点的一个方案
2009/10/26 Javascript
JScript 脚本实现文件下载 一般用于下载木马
2009/10/29 Javascript
Javascript 判断Flash是否加载完成的代码
2010/04/12 Javascript
js中数组排序sort方法的原理分析
2014/11/20 Javascript
js实现类似菜单风格的TAB选项卡效果代码
2015/08/28 Javascript
Jquery ajax加载等待执行结束再继续执行下面代码操作
2015/11/24 Javascript
原生js实现图片轮播特效
2015/12/18 Javascript
zTree插件下拉树使用入门教程
2016/04/11 Javascript
JavaScript类的写法
2016/09/17 Javascript
微信小程序 网络API发起请求详解
2016/11/09 Javascript
Node.js调试技术总结分享
2017/03/12 Javascript
node.JS md5加密中文与php结果不一致的解决方法
2017/05/05 Javascript
Vuejs中使用markdown服务器端渲染的示例
2017/11/22 Javascript
JS常见DOM节点操作示例【创建 ,插入,删除,复制,查找】
2018/05/14 Javascript
动态内存分配导致影响Javascript性能的问题
2018/12/18 Javascript
WEB前端性能优化的7大手段详解
2020/02/04 Javascript
python操作xml文件示例
2014/04/07 Python
python调用系统ffmpeg实现视频截图、http发送
2018/03/06 Python
无法使用pip命令安装python第三方库的原因及解决方法
2018/06/12 Python
简单了解python代码优化小技巧
2019/07/08 Python
Python人工智能之路 jieba gensim 最好别分家之最简单的相似度实现
2019/08/13 Python
pandas factorize实现将字符串特征转化为数字特征
2019/12/19 Python
Python selenium 自动化脚本打包成一个exe文件(推荐)
2020/01/14 Python
英国天然有机美容护肤品:Neal’s Yard Remedies
2018/05/05 全球购物
美国第一大药店连锁机构:Walgreens(沃尔格林)
2019/10/10 全球购物
Under Armour安德玛意大利官网:美国高端运动科技品牌
2020/01/16 全球购物
迟到检讨书800字
2014/01/13 职场文书
求职自荐信怎么写
2014/03/06 职场文书
投标承诺书怎么写
2014/05/24 职场文书
教师学习党的群众路线教育实践活动心得体会
2014/10/31 职场文书
2014年骨干教师工作总结
2014/12/19 职场文书
英语辞职信范文
2015/02/28 职场文书
2015年度物业公司工作总结
2015/04/27 职场文书