• 【转】简单的rpc实现(php)


    原文:https://www.jianshu.com/p/800849778461

    作者:谁不曾年少轻狂过
    链接:https://www.jianshu.com/p/800849778461

    第二个:echo $cli->getUserInfo(array('name' => '张三', 'age' => 27)); 调用

     对应的tcpdump 抓的包 tcpdump tcp port 8000 -w mm.pcap

    mm.pcap

    ------------------------------------------------------------------------------------------------------------------

    RPC全称为Remote Procedure Call,翻译过来为"远程过程调用"。主要应用于不同的系统之间的远程通信和相互调用。

    文件结构

     
    image.png

    User.php

    <?php
    
    /**
     * 服务文件
     * Class User
     */
    class User {
        /**
         * 获取用户ID
         * @return string
         */
        public function test() {
            // todo
            {
    
            }
            return '10000';
        }
    
        /**
         * 获取用户信息
         * @param $params
         * @return string
         */
        public function getUserInfo($params) {
            // todo
            {
    
            }
            return json_encode($params);
        }
    }
    

    RpcServer.php

    <?php
    
    /**
     * rpc 服务端
     * Class RpcServer
     */
    class RpcServer {
    
        protected $serv = null;
    
        /**
         * 创建rpc服务,映射RPC服务
         * RpcServer constructor.
         * @param $host
         * @param $port
         * @param $path
         */
        public function __construct($host, $port, $path) {
    
            //创建tcp socket服务
            $this->serv = stream_socket_server("tcp://{$host}:{$port}", $errno, $errstr);
            if (!$this->serv) {
                exit("{$errno} : {$errstr} 
    ");
            }
    
            //RPC服务目录是否存在
            $realPath = realpath(__DIR__ . $path);
            if ($realPath === false || !file_exists($realPath)) {
                exit("{$path} error 
    ");
            }
    
            //解析数据,执行业务逻辑
            while (true && $this->serv) {
                $client = stream_socket_accept($this->serv);
    
                if ($client) {
                    //读取并解析数据
                    $buf = fread($client, 2048);
                    $buf = json_decode($buf, true);
                    $class = $buf['class'];
                    $method = $buf['method'];
                    $params = $buf['params'];
    
                    //调用服务文件
                    if ($class && $method) {
                        $file = $realPath . '/' . $class . '.php';
                        if (file_exists($file)) {
                            require_once $file;
                            $obj = new $class();
                            //如果有参数,则传入指定参数
                            if (!$params) {
                                $data = $obj->$method();
                            } else {
                                $data = $obj->$method($params);
                            }
                            //返回结果
                            fwrite($client, $data);
                        }else{
                            fwrite($client,date('Y-m-d H:i:s')."	"."[$file] Service files do not exist.");
                        }
                    } else {
                        fwrite($client, 'class or method error');
                    }
                    //关闭客户端
                    fclose($client);
                }
            }
        }
    
        public function __destruct() {
            fclose($this->serv);
        }
    }
    
    new RpcServer('127.0.0.1', 8000, './service');
    
    

    RpcClient.php

    <?php
    
    /**
     * rpc 客户端
     * Class RpcClient
     */
    class RpcClient {
        protected $urlInfo = array();
    
        /**
         * 解析url
         * RpcClient constructor.
         * @param $url
         */
        public function __construct($url) {
            $this->urlInfo = parse_url($url);
            if(!$this->urlInfo) {
                exit("{$url} error 
    ");
            }
        }
    
        /**
         * 远程调用
         * @param $method
         * @param $params
         * @return string
         */
        public function __call($method, $params) {
            //创建一个客户端
            $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
            if (!$client) {
                exit("{$errno} : {$errstr} 
    ");
            }
            //采用json格式进行通讯
            $proto=array(
                //传递调用的类名
                'class'=>basename($this->urlInfo['path']),
                //传递调用的方法名
                'method'=>$method,
                //传递方法的参数
                'params'=>$params,
            );
            $protoData=json_encode($proto);
    
            //发送自定义的协议数据
            fwrite($client, $protoData);
            //读取服务端回传数据
            $data = fread($client, 2048);
            //关闭客户端
            fclose($client);
            return $data;
        }
    }
     
    $cli = new RpcClient('http://127.0.0.1:8000/User');
    echo $cli->test().PHP_EOL;
    echo $cli->getUserInfo(array('name' => '张三', 'age' => 27));
    

    启动server端

     
    image.png

    启动client端测试

     
    image.png

    要设计一个rpc框架,要做的不仅仅如此,大家个参考其他rpc框架

     
    网络图片.png

    持续更新~




  • 相关阅读:
    【二分】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem C. Careful Ascent
    【强连通分量缩点】【DFS】【动态规划】Urozero Autumn Training Camp 2016 Day 5: NWERC-2016 Problem B. British Menu
    【Splay】Codeforces Round #424 (Div. 1, rated, based on VK Cup Finals) B. Cards Sorting
    【Splay】bzoj3223 Tyvj 1729 文艺平衡树
    【Splay】bzoj3224 Tyvj 1728 普通平衡树
    【LIS】【递推】Gym
    【DFS】【枚举】Gym
    【递推】【DFS】【枚举】Gym
    【推导】Codeforces Round #424 (Div. 1, rated, based on VK Cup Finals) A. Office Keys
    【概率dp】【数学期望】Gym
  • 原文地址:https://www.cnblogs.com/oxspirt/p/12836247.html
Copyright © 2020-2023  润新知