作为程序员一定要保持良好的睡眠,才能好编程

RPC 第一课 使用PHP来简单的创建一个RPC服务

发布时间:2020-03-08


RpcServer.php

<?php
/**
 * Created by PhpStorm.
 * User: songyongzhan
 * Date: 2018/11/8
 * Time: 17:28
 * Email: songyongzhan@qianbao.com
 */

class RpcServer {


  protected $server = NULL;

  public function __construct($host, $port, $path) {

    $this->server = stream_socket_server(sprintf("tcp://%s:%s", $host, $port), $errno, $error);

    if (!$this->server) {
      exit("{$errno}:{$error}");
    }

    $realPath = realpath(__DIR__ . DIRECTORY_SEPARATOR . $path);
    if ($realPath === FALSE || !file_exists($realPath)) {
      exit("{$realPath} error.\n");
    }

    while (TRUE) {

      $client = @stream_socket_accept($this->server);

      if ($client) {
        //这里为了简单,我们一次性读取
        $buf = fread($client, 2048);
        //解析客户端发送过来的协议
        $classRet = preg_match('/Rpc-Class:\s(.*);[\r\n|\r|\n]?/i', $buf, $class);
        $methodRet = preg_match('/Rpc-Method:\s(.*);[\r\n|\r|\n]?/i', $buf, $method);
        $paramsRet = preg_match('/Rpc-Params:\s(.*);[\r\n|\r|\n]?/i', $buf, $params);

        printf("===================================\n");
        printf("classRet:%s   methodRet:%s  $paramsRet:%s  class:%s\n", $classRet, $methodRet,$paramsRet, json_encode($class));
        printf("===================================\n");
        if ($classRet && $methodRet) {
          $class = ucfirst($class[1]);
          $file = $realPath . '/' . $class . '.php';
          //判断文件是否存在,如果有,则引入文件
          if (file_exists($file)) {
            require_once $file;
            //实例化类,并调用客户端指定的方法
            $obj = new $class();
            //如果有参数,则传入指定参数
            if (!$paramsRet) {
              $data = call_user_func_array([$obj,$method[1]],[]);
            } else {
              $data = call_user_func_array([$obj,$method[1]],json_decode($params[1]));
            }
            //把运行后的结果返回给客户端
            fwrite($client, $data);
          }
        } else {
          fwrite($client, "class or method error\n");
        }
        //关闭客户端
        fclose($client);

      }


    }


  }


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

}


new RpcServer('127.0.0.1', 8888, 'static');


RpcClient.php

<?php
/**
 * Created by PhpStorm.
 * User: songyongzhan
 * Date: 2018/11/8
 * Time: 17:36
 * Email: songyongzhan@qianbao.com
 */
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;


    //printf($proto);
    //向服务端发送我们自定义的协议数据
    fwrite($client, $proto);
    //读取服务端传来的数据
    $data = fread($client, 2048);
    //关闭客户端
    fclose($client);
    return $data;
  }


}


$cli = new RpcClient('http://127.0.0.1:8888/test');
//echo $cli->hehe(['name'=>'james'],'13');
echo $cli->hehe('james','13')."\n";
echo $cli->hehe2(array('name' => 'test', 'age' => 27))."\n";


static/Test.php

<?php
/**
 * Created by PhpStorm.
 * User: songyongzhan
 * Date: 2018/11/8
 * Time: 17:43
 * Email: songyongzhan@qianbao.com
 */

class Test {
  public function hehe($name, $age) {
    return sprintf('hello %s age:%d', $name, $age);
  }

  public function hehe2($params) {
    return json_encode($params);
  }
}



启动方式:

1、php RpcServer.php

2、php RpcClient.php


服务器端:



客户端


整体的目录架构是:


dir.png



请访问这个地址查看:


http://www.cnblogs.com/jkko123/p/6574808.html