• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    PHP创建简单RPC服务案例详解

    RPC 定义

    RPC(Remote Procedure Call)即远程过程调用,指被调用方法的具体实现不在程序运行本地,而是在别的某个地方。主要应用于不同的系统之间的远程通信和相互调用。

    如 A 调用 B 提供的 remoteAdd 方法:

    1. 首先A与B之间建立一个TCP连接;
    2. 然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送出去;
    3. B接受A发送过来的字节流,然后反序列化得到目标方法名,方法参数,接着执行相应的方法调用(可能是localAdd)并把结果30返回;
    4. A接受远程调用结果

    有些远程调用选择比较底层的 socket 协议,有些远程调用选择比较上层的 HTTP 协议。

    远程调用的好处:

    这里使用 PHP Socket 来创建一个服务端和客户端,目录结构如下:

    服务端 

    ?php
    class RpcServer {
        protected $server = null;
    
        public function __construct($host, $port, $path)
        {
            // 创建一个 Socket 服务
            if(($this->server = socket_create(AF_INET,SOCK_STREAM,SOL_TCP))  0) {
                exit("socket_create() 失败的原因是:".socket_strerror($this->server)."\n");
            }
            if(($ret = socket_bind($this->server,$host,$port))  0) {
                exit("socket_bind() 失败的原因是:".socket_strerror($ret)."\n");
            }
            if(($ret = socket_listen($this->server,3))  0) {
                exit("socket_listen() 失败的原因是:".socket_strerror($ret)."\n");
            }
    
            // 判断 RPC 服务目录是否存在
            $realPath = realpath(__DIR__ . $path);
            if ($realPath === false || !file_exists($realPath)) {
                exit("{$path} error \n");
            }
    
            do {
                $client = socket_accept($this->server);
                if($client) {
                    // 一次性读取
                    $buf = socket_read($client, 8024);
                    echo $buf;
    
                    //解析客户端发送过来的协议
                    $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]);
                        $method = $method[1];
                        $params = json_decode($params[1], true);
                        $file = $realPath . '/' . $class . '.php';  // 类文件需要和类名一致
                        $data = ''; // 执行结果
                        // 判断类文件是否存在
                        if(file_exists($file)) {
                            // 引入类文件
                            require_once $file;
                            // 实例化类
                            $rfc_obj = new ReflectionClass($class);
                            // 判断该类指定方法是否存在
                            if($rfc_obj->hasMethod($method)) {
                                // 执行类方法
                                $rfc_method = $rfc_obj->getMethod($method);
                                $data = $rfc_method->invokeArgs($rfc_obj->newInstance(), [$params]);
                            } else {
                                socket_write($client, 'method error');
                            }
                            //把运行后的结果返回给客户端
                            socket_write($client, $data);
                        }
                    } else {
                        socket_write($client, 'class or method error');
                    }
    
                    // 关闭客户端
                    socket_close($client);
                }
    
            }while(true);
        }
    
        public function __destruct()
        {
            socket_close($this->server);
        }
    }
    
    new RpcServer('127.0.0.1',8080,'./service');

    客户端

    ?php
    class RpcClient {
        protected $client = null;
        protected $url_info = [];   // 远程调用 URL 组成部分
    
        public function __construct($url)
        {
            // 解析 URL
            $this->url_info = parse_url($url);
        }
    
        public function __call($name, $arguments)
        {
            // 创建一个客户端
            $this->client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
            if(!$this->client) {
                exit('socket_create() 失败');
            }
            socket_connect($this->client, $this->url_info['host'], $this->url_info['port']);
    
            // 传递调用的类名
            $class = basename($this->url_info['path']);
            // 传递调用的参数
            $args = '';
            if(isset($arguments[0])) {
                $args = json_encode($arguments[0]);
            }
            // 向服务端发送我们自定义的协议数据
            $proto = "Rpc-Class: {$class};".PHP_EOL
                ."Rpc-Method: {$name};".PHP_EOL
                ."Rpc-Params: {$args};".PHP_EOL;
            socket_write($this->client, $proto);
            // 读取服务端传来的数据
            $buf = socket_read($this->client, 8024);
            socket_close($this->client);
            return $buf;
        }
    }
    
    $rpcClient = new RpcClient('http://127.0.0.1:8080/news');
    echo $rpcClient->display(['title'=>'txl']);
    echo $rpcClient->display(['title'=>'hello world']);

    服务类 News

    ?php
    class News {
        public function display($data)
        {
            return json_encode(['result'=>"News display(), title is {$data['title']}"]);
        }
    }

    运行测试:

    Client

    Server

    到此这篇关于PHP创建简单RPC服务案例详解的文章就介绍到这了,更多相关PHP创建简单RPC服务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • 详解php中流行的rpc框架
    • php实现的一个简单json rpc框架实例
    • PHP采用XML-RPC构造Web Service实例教程
    • AMFPHP php远程调用(RPC, Remote Procedure Call)工具 快速入门教程
    • php xml-rpc远程调用
    上一篇:PHP8新特性之JIT案例讲解
    下一篇:PHP实现WebSocket实例详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    PHP创建简单RPC服务案例详解 PHP,创建,简单,RPC,服务,案例,