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在Web开发领域的优势
Oct 09 PHP
如何跨站抓取别的站点的页面的补充
Oct 09 PHP
Discuz 模板语句分析及知识技巧
Aug 21 PHP
PHP中改变图片的尺寸大小的代码
Jul 17 PHP
PHP rawurlencode与urlencode函数的深入分析
Jun 08 PHP
美图秀秀web开放平台--PHP流式上传和表单上传示例分享
Jun 22 PHP
php银联网页支付实现方法
Mar 04 PHP
PHP中的Trait 特性及作用
Apr 03 PHP
动态表单验证的操作方法和TP框架里面的ajax表单验证
Jul 19 PHP
ThinkPHP5框架缓存查询操作分析
May 30 PHP
实例介绍PHP删除数组中的重复元素
Mar 03 PHP
PHP mkdir创建文件夹实现方法解析
Nov 13 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导出到Excel或CSV的详解(附utf8、gbk 编码转换)
2013/06/25 PHP
PHP内置过滤器FILTER使用实例
2014/06/25 PHP
详解WordPress中简码格式标签编写的基本方法
2015/12/22 PHP
php实现三级级联下拉框
2016/04/17 PHP
js用图作提交按钮或超连接
2008/03/26 Javascript
jquery模拟按下回车实现代码
2011/09/20 Javascript
JavaScript实现的石头剪刀布游戏源码分享
2014/08/22 Javascript
详解Javascript动态操作CSS
2014/12/08 Javascript
jQuery的基本概念与高级编程
2015/05/14 Javascript
javascript框架设计之框架分类及主要功能
2015/06/23 Javascript
jQuery移动web开发之页面跳转和加载外部页面的实现
2015/12/04 Javascript
AngularJS ng-controller 指令简单实例
2016/08/01 Javascript
用nodejs的实现原理和搭建服务器(动态)
2016/08/10 NodeJs
js仿搜狐视频记录片列表展示效果
2020/05/30 Javascript
利用JS对iframe父子(内外)页面进行操作的方法教程
2017/06/15 Javascript
浅析JavaScript中的平稳退化(graceful degradation)
2017/07/24 Javascript
vue-cli构建vue项目的步骤详解
2019/01/27 Javascript
vue实现移动端图片上传功能
2019/12/23 Javascript
JS判断浏览器类型与操作系统的方法分析
2020/04/30 Javascript
[00:56]PWL开团时刻DAY8——追追追追追!
2020/11/09 DOTA
深度剖析使用python抓取网页正文的源码
2014/06/11 Python
简单介绍Python中利用生成器实现的并发编程
2015/05/04 Python
python numpy实现文件存取的示例代码
2019/05/26 Python
pytorch自定义二值化网络层方式
2020/01/07 Python
Python实现打包成库供别的模块调用
2020/07/13 Python
Python 如何查找特定类型文件
2020/08/17 Python
Python通过fnmatch模块实现文件名匹配
2020/09/30 Python
海滩咖啡馆:Beach Cafe
2018/02/02 全球购物
在C#中如何实现多态
2014/07/02 面试题
幼儿园国庆节活动方案
2014/02/01 职场文书
无传销社区工作方案
2014/05/13 职场文书
2014年基建工作总结
2014/12/12 职场文书
体检通知范文
2015/04/21 职场文书
2015年公路路政个人工作总结
2015/07/24 职场文书
有关浪费资源的建议书
2015/09/14 职场文书
导游词之铁岭象牙山
2019/12/06 职场文书