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 相关文章推荐
简单采集了yahoo的一些数据
Feb 14 PHP
php+iframe实现隐藏无刷新上传文件
Feb 10 PHP
php调用dll的实例操作动画与代码分享
Aug 14 PHP
深入解析php中的foreach函数
Aug 31 PHP
php像数组一样存取和修改字符串字符
Mar 21 PHP
php实现的日历程序
Jun 18 PHP
php发送邮件的问题详解
Jun 22 PHP
php版微信公众账号第三方管理工具开发简明教程
Sep 23 PHP
php通过PHPExcel导入Excel表格到MySQL数据库的简单实例
Oct 29 PHP
PHP实现求解最长公共子串问题的方法
Nov 17 PHP
PHP SPL 被遗落的宝石【SPL应用浅析】
Apr 20 PHP
50个优秀经典PHP算法大集合 附源码
Aug 26 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 header示例代码(推荐)
2010/09/08 PHP
教你如何开启shopnc b2b2c 伪静态
2014/10/21 PHP
PHP将字符分解为多个字符串的方法
2014/11/22 PHP
Codeigniter发送邮件的方法
2015/03/19 PHP
详解Yii2 定制表单输入字段的标签和样式
2017/01/04 PHP
你必须知道的Javascript知识点之&quot;this指针&quot;的应用
2013/04/23 Javascript
jQuery获取页面元素绝对与相对位置的方法
2015/06/10 Javascript
javascript基于prototype实现类似OOP继承的方法
2015/12/16 Javascript
浅析jQuery中使用$所引发的问题
2016/05/29 Javascript
jQuery 3.0十大新特性
2016/07/06 Javascript
JavaScript使用Range调色及透明度实例
2016/09/25 Javascript
百度地图API之百度地图退拽标记点获取经纬度的实现代码
2017/01/12 Javascript
select下拉框插件jquery.editable-select详解
2017/01/22 Javascript
jQuery实现表格奇偶行显示不同背景色 就这么简单
2017/03/13 Javascript
Vue2.0生命周期的理解
2018/08/20 Javascript
Vue.js 中 axios 跨域访问错误问题及解决方法
2018/11/21 Javascript
微信小程序实现商品属性联动选择
2019/02/15 Javascript
js Array.slice的8种不同用法示例
2019/07/10 Javascript
基于Vue的商品主图放大镜方案详解
2019/09/19 Javascript
js实现简单的打印表格
2020/01/15 Javascript
JavaScript检测是否开启了控制台(F12调试工具)
2020/10/02 Javascript
零基础写python爬虫之urllib2中的两个重要概念:Openers和Handlers
2014/11/05 Python
使用Scrapy爬取动态数据
2018/10/21 Python
python 求一个列表中所有元素的乘积实例
2019/06/11 Python
用Python配平化学方程式的方法
2019/07/20 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
如何定义一个可复用的服务
2014/09/30 面试题
机电专业毕业生推荐信
2013/11/10 职场文书
办理护照介绍信
2014/01/16 职场文书
物流专员岗位职责
2014/02/17 职场文书
2014年党的群众路线教育实践活动总结
2014/04/25 职场文书
《鲁班和橹板》教学反思
2014/04/27 职场文书
学校领导班子成员查摆问题及整改措施
2014/10/28 职场文书
vue点击弹窗自动触发点击事件的解决办法(模拟场景)
2021/05/25 Vue.js
浅谈Golang 切片(slice)扩容机制的原理
2021/06/09 Golang
tp5使用layui实现多个图片上传(带附件选择)的方法实例
2021/11/17 PHP