濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)案例詳解

PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)案例詳解

熱門(mén)標(biāo)簽:400電話個(gè)人能不能辦理 手機(jī)外呼系統(tǒng)什么原理 溫州外呼系統(tǒng)招商 凱立德地鐵站地圖標(biāo)注 合肥ai電銷(xiāo)機(jī)器人費(fèi)用 上海400客服電話怎么申請(qǐng) 天津電銷(xiāo)外呼系統(tǒng)違法嗎 滄州電銷(xiāo)外呼系統(tǒng)價(jià)格 銀行信貸電話機(jī)器人

RPC 定義

RPC(Remote Procedure Call)即遠(yuǎn)程過(guò)程調(diào)用,指被調(diào)用方法的具體實(shí)現(xiàn)不在程序運(yùn)行本地,而是在別的某個(gè)地方。主要應(yīng)用于不同的系統(tǒng)之間的遠(yuǎn)程通信和相互調(diào)用。

如 A 調(diào)用 B 提供的 remoteAdd 方法:

  1. 首先A與B之間建立一個(gè)TCP連接;
  2. 然后A把需要調(diào)用的方法名(這里是remoteAdd)以及方法參數(shù)(10, 20)序列化成字節(jié)流發(fā)送出去;
  3. B接受A發(fā)送過(guò)來(lái)的字節(jié)流,然后反序列化得到目標(biāo)方法名,方法參數(shù),接著執(zhí)行相應(yīng)的方法調(diào)用(可能是localAdd)并把結(jié)果30返回;
  4. A接受遠(yuǎn)程調(diào)用結(jié)果

有些遠(yuǎn)程調(diào)用選擇比較底層的 socket 協(xié)議,有些遠(yuǎn)程調(diào)用選擇比較上層的 HTTP 協(xié)議。

遠(yuǎn)程調(diào)用的好處:

  • 解耦:當(dāng)方法提供者需要對(duì)方法內(nèi)實(shí)現(xiàn)修改時(shí),調(diào)用者完全感知不到,不用做任何變更;這種方式在跨部門(mén),跨公司合作的時(shí)候經(jīng)常用到,并且方法的提供者我們通常稱(chēng)為:服務(wù)的暴露方

這里使用 PHP Socket 來(lái)創(chuàng)建一個(gè)服務(wù)端和客戶(hù)端,目錄結(jié)構(gòu)如下:

服務(wù)端 

?php
class RpcServer {
    protected $server = null;

    public function __construct($host, $port, $path)
    {
        // 創(chuàng)建一個(gè) Socket 服務(wù)
        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 服務(wù)目錄是否存在
        $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;

                //解析客戶(hù)端發(fā)送過(guò)來(lái)的協(xié)議
                $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';  // 類(lèi)文件需要和類(lèi)名一致
                    $data = ''; // 執(zhí)行結(jié)果
                    // 判斷類(lèi)文件是否存在
                    if(file_exists($file)) {
                        // 引入類(lèi)文件
                        require_once $file;
                        // 實(shí)例化類(lèi)
                        $rfc_obj = new ReflectionClass($class);
                        // 判斷該類(lèi)指定方法是否存在
                        if($rfc_obj->hasMethod($method)) {
                            // 執(zhí)行類(lèi)方法
                            $rfc_method = $rfc_obj->getMethod($method);
                            $data = $rfc_method->invokeArgs($rfc_obj->newInstance(), [$params]);
                        } else {
                            socket_write($client, 'method error');
                        }
                        //把運(yùn)行后的結(jié)果返回給客戶(hù)端
                        socket_write($client, $data);
                    }
                } else {
                    socket_write($client, 'class or method error');
                }

                // 關(guān)閉客戶(hù)端
                socket_close($client);
            }

        }while(true);
    }

    public function __destruct()
    {
        socket_close($this->server);
    }
}

new RpcServer('127.0.0.1',8080,'./service');

客戶(hù)端

?php
class RpcClient {
    protected $client = null;
    protected $url_info = [];   // 遠(yuǎn)程調(diào)用 URL 組成部分

    public function __construct($url)
    {
        // 解析 URL
        $this->url_info = parse_url($url);
    }

    public function __call($name, $arguments)
    {
        // 創(chuàng)建一個(gè)客戶(hù)端
        $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']);

        // 傳遞調(diào)用的類(lèi)名
        $class = basename($this->url_info['path']);
        // 傳遞調(diào)用的參數(shù)
        $args = '';
        if(isset($arguments[0])) {
            $args = json_encode($arguments[0]);
        }
        // 向服務(wù)端發(fā)送我們自定義的協(xié)議數(shù)據(jù)
        $proto = "Rpc-Class: {$class};".PHP_EOL
            ."Rpc-Method: {$name};".PHP_EOL
            ."Rpc-Params: {$args};".PHP_EOL;
        socket_write($this->client, $proto);
        // 讀取服務(wù)端傳來(lái)的數(shù)據(jù)
        $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']);

服務(wù)類(lèi) News

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

運(yùn)行測(cè)試:

Client

Server

到此這篇關(guān)于PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)案例詳解的文章就介紹到這了,更多相關(guān)PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

您可能感興趣的文章:
  • 詳解php中流行的rpc框架
  • php實(shí)現(xiàn)的一個(gè)簡(jiǎn)單json rpc框架實(shí)例
  • PHP采用XML-RPC構(gòu)造Web Service實(shí)例教程
  • AMFPHP php遠(yuǎn)程調(diào)用(RPC, Remote Procedure Call)工具 快速入門(mén)教程
  • php xml-rpc遠(yuǎn)程調(diào)用

標(biāo)簽:白城 赤峰 洛陽(yáng) 酒泉 七臺(tái)河 金華 溫州 怒江

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)案例詳解》,本文關(guān)鍵詞  PHP,創(chuàng)建,簡(jiǎn)單,RPC,服務(wù),案例,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)案例詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于PHP創(chuàng)建簡(jiǎn)單RPC服務(wù)案例詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    淳化县| 雷山县| 开阳县| 屯留县| 平度市| 宜宾市| 临桂县| 尼玛县| 南城县| 伊金霍洛旗| 海南省| 郯城县| 沐川县| 深泽县| 张家界市| 乳山市| 安塞县| 高淳县| 潞西市| 尼勒克县| 泰宁县| 西贡区| 朝阳县| 滨州市| 湘阴县| 深泽县| 时尚| 临潭县| 崇州市| 永修县| 宁夏| 十堰市| 克拉玛依市| 西安市| 万盛区| 海安县| 志丹县| 辽宁省| 南乐县| 棋牌| 清水河县|