亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

PHP如何創建簡單RPC服務

發布時間:2021-09-07 10:29:32 來源:億速云 閱讀:134 作者:小新 欄目:開發技術

小編給大家分享一下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如何創建簡單RPC服務

服務端 

<?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

PHP如何創建簡單RPC服務

Server

PHP如何創建簡單RPC服務

以上是“PHP如何創建簡單RPC服務”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

兴业县| 华亭县| 莱州市| 华宁县| 榆林市| 东明县| 自贡市| 开化县| 沅江市| 临潭县| 泸州市| 齐河县| 吴旗县| 定兴县| 嘉荫县| 平阳县| 香港| 金湖县| 乐业县| 尼木县| 永仁县| 凤山市| 白玉县| 孟村| 甘洛县| 湖口县| 宜城市| 民和| 巴林右旗| 进贤县| 淮南市| 汝阳县| 绍兴市| 夹江县| 仙游县| 淮北市| 会宁县| 贵溪市| 钟祥市| 九寨沟县| 沧源|