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制作图型计数器的例子
Oct 09 PHP
用php实现像JSP,ASP里Application那样的全局变量
Jan 12 PHP
php5中类的学习
Mar 28 PHP
php设计模式 Observer(观察者模式)
Jun 26 PHP
php读取txt文件组成SQL并插入数据库的代码(原创自Zjmainstay)
Jul 31 PHP
php中计算程序运行时间的类代码
Nov 03 PHP
基于php在各种web服务器的运行模式详解
Jun 03 PHP
一个简单安全的PHP验证码类 附调用方法
Jun 24 PHP
Yii框架分页实现方法详解
May 20 PHP
PHP封装的XML简单操作类完整实例
Nov 13 PHP
thinkphp5框架结合mysql实现微信登录和自定义分享链接与图文功能示例
Aug 13 PHP
PHP控制循环操作的时间
Apr 01 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 debug 安装技巧
2011/04/30 PHP
php截取中文字符串函数实例
2015/02/23 PHP
PHP借助phpmailer发送邮件
2015/05/11 PHP
浅谈COOKIE和SESSION区别
2015/07/19 PHP
PHP邮件群发机实现代码
2016/02/16 PHP
PHP实现电商订单自动确认收货redis队列
2017/05/17 PHP
php 字符串中是否包含指定字符串的多种方法
2018/04/12 PHP
php实现单笔转账到支付宝功能
2018/10/09 PHP
优化 JavaScript 代码的方法小结
2009/07/16 Javascript
简洁短小的 JavaScript IE 浏览器判定代码
2010/03/21 Javascript
js动态生成指定行数的表格
2013/07/11 Javascript
jQuery设置与获取HTML,文本和值的简单实例
2014/02/26 Javascript
Android中的jQuery:AQuery简介
2014/05/06 Javascript
轻松创建nodejs服务器(1):一个简单nodejs服务器例子
2014/12/18 NodeJs
JavaScript仿商城实现图片广告轮播实例代码
2016/02/06 Javascript
JS中Eval解析JSON字符串的一个小问题
2016/02/21 Javascript
js传值后台中文出现乱码的解决方法
2016/06/30 Javascript
jQuery监听浏览器窗口大小的变化实例
2017/02/07 Javascript
利用jQuery实现滑动开关按钮效果(附demo源码下载)
2017/02/07 Javascript
Vue 仿百度搜索功能实现代码
2017/02/16 Javascript
微信小程序中的swiper组件详解
2017/04/14 Javascript
vue-cli构建项目使用 less的方法
2017/10/04 Javascript
Vue组件创建和传值的方法
2018/08/17 Javascript
layui-table对返回的数据进行转变显示的实例
2019/09/04 Javascript
[02:40]2014DOTA2 国际邀请赛中国区预选赛 四大豪门抵达华西村
2014/05/23 DOTA
python学生管理系统代码实现
2020/04/05 Python
Python实现通过继承覆盖方法示例
2018/07/02 Python
python3 requests库文件上传与下载实现详解
2019/08/22 Python
在TensorFlow中实现矩阵维度扩展
2020/05/22 Python
美国专业消费电子及摄影器材网站:B&H Photo Video
2019/12/18 全球购物
技术总监个人的自我评价范文
2013/12/18 职场文书
兰兰过桥教学反思
2014/02/08 职场文书
医院护士见习期自我鉴定
2014/09/15 职场文书
销售员岗位职责范本
2015/04/11 职场文书
宣传委员竞选稿
2015/11/19 职场文书
详解Python中的进程和线程
2021/06/23 Python