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与paypal整合方法
Nov 28 PHP
11个PHP 分页脚本推荐
Aug 15 PHP
探讨:如何编写PHP扩展
Jun 13 PHP
PHP基础知识介绍
Sep 17 PHP
PHP中iconv函数转码时截断字符问题的解决方法
Jan 21 PHP
在Debian系统下配置LNMP的教程
Jul 09 PHP
PHP magento后台无法登录问题解决方法
Nov 24 PHP
PHP会话控制实例分析
Dec 24 PHP
浅谈PHP面向对象之访问者模式+组合模式
May 22 PHP
laravel5实现微信第三方登录功能
Dec 06 PHP
PHP实现的用户注册表单验证功能简单示例
Feb 25 PHP
PHP实现Snowflake生成分布式唯一ID的方法示例
Aug 30 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 getsiteurl()函数
2009/09/05 PHP
md5 16位二进制与32位字符串相互转换示例
2013/12/30 PHP
php 字符串中的\n换行符无效、不能换行的解决方法
2014/04/02 PHP
CodeIgniter配置之autoload.php自动加载用法分析
2016/01/20 PHP
浅谈PHP表单提交(POST&amp;GET&amp;URL编/解码)
2017/04/03 PHP
PHP基于openssl实现的非对称加密操作示例
2019/01/11 PHP
js 对象是否存在判断
2009/07/15 Javascript
解决iframe的frameborder在chrome/ff/ie下的差异
2010/08/12 Javascript
非常漂亮的JS+CSS图片幻灯切换特效
2013/11/20 Javascript
BootStrap的JS插件之轮播效果案例详解
2016/05/16 Javascript
jQuery前端开发35个小技巧
2016/05/24 Javascript
Vue.js框架路由使用方法实例详解
2017/08/25 Javascript
jQuery EasyUI window窗口使用实例代码
2017/12/25 jQuery
JavaScript实现区块链
2018/03/14 Javascript
浅谈Angular7 项目开发总结
2018/12/19 Javascript
如何获取vue单文件自身源码路径
2019/05/06 Javascript
使用Vue-cli3.0创建的项目 如何发布npm包
2019/10/10 Javascript
JavaScript数组去重实现方法小结
2020/01/17 Javascript
Mac OS X10.9安装的Python2.7升级Python3.3步骤详解
2013/12/04 Python
Python读取mp3中ID3信息的方法
2015/03/05 Python
Python中的groupby分组功能的实例代码
2018/07/11 Python
matplotlib给子图添加图例的方法
2018/08/03 Python
python学生管理系统的实现
2020/04/05 Python
keras 如何保存最佳的训练模型
2020/05/25 Python
HTML5 与 XHTML2
2008/10/17 HTML / CSS
canvas如何绘制钟表的方法
2017/12/13 HTML / CSS
荷兰网上鞋店:Ziengs.nl
2017/01/02 全球购物
台湾演唱会订票网站:StubHub台湾
2019/06/11 全球购物
德国最大的婴儿用品网上商店:Kidsroom.de(支持中文)
2020/09/02 全球购物
药剂学专业应届生自荐信
2013/09/29 职场文书
金融专业应届生求职信
2013/11/02 职场文书
银行授权委托书样本
2014/10/13 职场文书
党的群众路线教育实践活动个人整改措施
2014/10/27 职场文书
幼儿园见习报告范文
2014/10/30 职场文书
安全第一课观后感
2015/06/18 职场文书
Java后端 Dubbo retries 超时重试机制的解决方案
2022/04/14 Java/Android