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 相关文章推荐
数字转英文
Dec 06 PHP
Linux下 php5 MySQL5 Apache2 phpMyAdmin ZendOptimizer安装与配置[图文]
Nov 18 PHP
基于PHP一些十分严重的缺陷详解
Jun 03 PHP
Windows中使用计划任务自动执行PHP程序实例
May 09 PHP
PHP实现的博客欢迎提示功能(很特别哦)
Jun 05 PHP
详谈PHP编码转换问题
Jul 28 PHP
php获得客户端浏览器名称及版本的方法(基于ECShop函数)
Dec 23 PHP
详解php中的implements 使用
Jun 13 PHP
Joomla框架实现字符串截取的方法示例
Jul 18 PHP
浅谈PHP中new self()和new static()的区别
Aug 11 PHP
laravel框架使用极光推送消息操作示例
Feb 15 PHP
PHP isset empty函数相关面试题及解析
Dec 11 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中实现中文字符进制转换原理分析
2011/12/06 PHP
php 文本文件的读取效率
2012/02/10 PHP
php中防止SQL注入的最佳解决方法
2013/04/25 PHP
浅谈PHP进程管理
2019/03/08 PHP
Mootools 1.2教程 设置和获取样式表属性
2009/09/15 Javascript
Tab页界面,用jQuery及Ajax技术实现
2009/09/21 Javascript
清空上传控件input file的值
2010/07/03 Javascript
纯js简单日历实现代码
2013/10/05 Javascript
JS实现自动变换的菜单效果代码
2015/09/09 Javascript
jquery制作属于自己的select自定义样式
2015/11/23 Javascript
快速实现JS图片懒加载(可视区域加载)示例代码
2017/01/04 Javascript
微信小程序 radio单选框组件详解及实例代码
2017/01/10 Javascript
Vue.js特性Scoped Slots的浅析
2019/02/20 Javascript
layui table去掉右侧滑动条的实现方法
2019/09/05 Javascript
vue轮播组件实现$children和$parent 附带好用的gif录制工具
2019/09/26 Javascript
在Python中使用PIL模块对图片进行高斯模糊处理的教程
2015/05/05 Python
Python自定义简单图轴简单实例
2018/01/08 Python
详解python3中zipfile模块用法
2018/06/18 Python
python破解bilibili滑动验证码登录功能
2019/09/11 Python
Python3+Requests+Excel完整接口自动化测试框架的实现
2019/10/11 Python
python yield关键词案例测试
2019/10/15 Python
Python高级property属性用法实例分析
2019/11/19 Python
Java多线程实现四种方式原理详解
2020/06/02 Python
Python 的 __str__ 和 __repr__ 方法对比
2020/09/02 Python
美国床垫连锁店:Mattress Firm
2021/02/13 全球购物
专营店会计助理岗位职责
2013/11/29 职场文书
文明礼仪小标兵事迹
2014/01/12 职场文书
汉语言文学毕业生自荐信范文
2014/03/24 职场文书
生日庆典策划方案
2014/06/02 职场文书
演讲稿开场白台词
2014/08/25 职场文书
黄石寨导游词
2015/02/05 职场文书
计算机专业自荐信
2015/03/05 职场文书
2015年底工作总结范文
2015/05/15 职场文书
python之基数排序的实现
2021/07/26 Python
Nginx实现负载均衡的项目实践
2022/03/18 Servers
springboot+zookeeper实现分布式锁
2022/03/21 Java/Android