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 相关文章推荐
第七节--类的静态成员
Nov 16 PHP
解决MySQL中文输出变成问号的问题
Jun 05 PHP
php addslashes 函数详细分析说明
Jun 23 PHP
php实现jQuery扩展函数
Oct 30 PHP
php数组中删除元素的实现代码
Jun 22 PHP
php数组(array)输出的三种形式详解
Jun 05 PHP
PHP删除目录及目录下所有文件的方法详解
Jun 06 PHP
php 模拟GMAIL,HOTMAIL(MSN),YAHOO,163,126邮箱登录的详细介绍
Jun 18 PHP
PHP删除数组中空值的方法介绍
Apr 14 PHP
php实现window平台的checkdnsrr函数
May 27 PHP
PHP实现生成唯一会员卡号
Aug 24 PHP
php实现的二叉树遍历算法示例
Jun 15 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错误日志简单配置方法
2016/07/11 PHP
php 多个变量指向同一个引用($b = &amp;$a)用法分析
2019/11/13 PHP
js树形控件脚本代码
2008/07/24 Javascript
JS在可编辑的div中的光标位置插入内容的方法
2014/11/20 Javascript
让javascript加载速度倍增的方法(解决JS加载速度慢的问题)
2014/12/12 Javascript
jQuery实现设置、移除文本框默认值功能
2015/01/13 Javascript
javascript实现可全选、反选及删除表格的方法
2015/05/15 Javascript
node.js缺少mysql模块运行报错的解决方法
2016/11/13 Javascript
浅析JavaScript中作用域和作用域链
2016/12/06 Javascript
vue数据双向绑定原理解析(get &amp; set)
2017/03/08 Javascript
JavaScript中splice与slice的区别
2017/05/09 Javascript
详解node child_process模块学习笔记
2018/01/24 Javascript
webpack之devtool详解
2018/02/10 Javascript
微信小程序实现分享到朋友圈功能
2018/07/19 Javascript
用Cordova打包Vue项目的方法步骤
2019/02/02 Javascript
vue使用高德地图点击下钻上浮效果的实现思路
2019/10/12 Javascript
Python获取单个程序CPU使用情况趋势图
2015/03/10 Python
Hadoop中的Python框架的使用指南
2015/04/22 Python
Python实现PS图像抽象画风效果的方法
2018/01/23 Python
python opencv 图像尺寸变换方法
2018/04/02 Python
python 根据时间来生成唯一的字符串方法
2019/01/14 Python
Python中的集合介绍
2019/01/28 Python
如何用OpenCV -python3实现视频物体追踪
2019/12/04 Python
html Table 表头固定的实现
2019/01/22 HTML / CSS
全球性的在线婚纱礼服工厂:27dress.com
2019/03/21 全球购物
《那片绿绿的爬山虎》教学反思
2014/02/27 职场文书
给校长的一封建议书
2014/03/12 职场文书
市场拓展计划书
2014/05/03 职场文书
中秋晚会活动方案
2014/08/31 职场文书
忠诚教育心得体会
2014/09/03 职场文书
关于上班时间调整的通知
2015/04/23 职场文书
红色故事汇观后感
2015/06/18 职场文书
单位领导婚礼致辞
2015/07/28 职场文书
外出培训学习心得体会
2016/01/18 职场文书
坚持不是死撑,更重要的是心态
2019/08/19 职场文书
Pygame Event事件模块的详细示例
2021/11/17 Python