- 1 <?php
- 2 /**
- 3 * User: yuzhao
- 4 * CreateTime: 2018/11/15 下午11:46
- 5 * Description: Rpc服务端
- 6 */
- 7 class RpcServer {
- 8
- 9 /**
- 10 * User: yuzhao
- 11 * CreateTime: 2018/11/15 下午11:51
- 12 * @var array
- 13 * Description: 此类的基本配置
- 14 */
- 15 private $params = [
- 16 'host' => '', // ip地址,列出来的目的是为了友好看出来此变量中存储的信息
- 17 'port' => '', // 端口
- 18 'path' => '' // 服务目录
- 19 ];
- 20
- 21 /**
- 22 * User: yuzhao
- 23 * CreateTime: 2018/11/16 上午12:14
- 24 * @var array
- 25 * Description: 本类常用配置
- 26 */
- 27 private $config = [
- 28 'real_path' => '',
- 29 'max_size' => 2048 // 最大接收数据大小
- 30 ];
- 31
- 32 /**
- 33 * User: yuzhao
- 34 * CreateTime: 2018/11/15 下午11:50
- 35 * @var nul
- 36 * Description:
- 37 */
- 38 private $server = null;
- 39
- 40 /**
- 41 * Rpc constructor.
- 42 */
- 43 public function __construct($params)
- 44 {
- 45 $this->check();
- 46 $this->init($params);
- 47 }
- 48
- 49 /**
- 50 * User: yuzhao
- 51 * CreateTime: 2018/11/16 上午12:0
- 52 * Description: 必要验证
- 53 */
- 54 private function check() {
- 55 $this->serverPath();
- 56 }
- 57
- 58 /**
- 59 * User: yuzhao
- 60 * CreateTime: 2018/11/15 下午11:48
- 61 * Description: 初始化必要参数
- 62 */
- 63 private function init($params) {
- 64 // 将传递过来的参数初始化
- 65 $this->params = $params;
- 66 // 创建tcpsocket服务
- 67 $this->createServer();
- 68 }
- 69
- 70 /**
- 71 * User: yuzhao
- 72 * CreateTime: 2018/11/16 上午12:0
- 73 * Description: 创建tcpsocket服务
- 74
- 75 */
- 76 private function createServer() {
- 77 $this->server = stream_socket_server("tcp://{$this->params['host']}:{$this->params['port']}", $errno,$errstr);
- 78 if (!$this->server) exit([
- 79 $errno,$errstr
- 80 ]);
- 81 }
- 82
- 83 /**
- 84 * User: yuzhao
- 85 * CreateTime: 2018/11/15 下午11:57
- 86 * Description: rpc服务目录
- 87 */
- 88 public function serverPath() {
- 89 $path = $this->params['path'];
- 90 $realPath = realpath(__DIR__ . $path);
- 91 if ($realPath === false ||!file_exists($realPath)) {
- 92 exit("{$path} error!");
- 93 }
- 94 $this->config['real_path'] = $realPath;
- 95 }
- 96
- 97 /**
- 98 * User: yuzhao
- 99 * CreateTime: 2018/11/15 下午11:51
- 100 * Description: 返回当前对象
- 101 */
- 102 public static function instance($params) {
- 103 return new RpcServer($params);
- 104 }
- 105
- 106 /**
- 107 * User: yuzhao
- 108 * CreateTime: 2018/11/16 上午12:06
- 109 * Description: 运行
- 110 */
- 111 public function run() {
- 112 while (true) {
- 113 $client = stream_socket_accept($this->server);
- 114 if ($client) {
- 115 echo "有新连接\n";
- 116 $buf = fread($client, $this->config['max_size']);
- 117 print_r('接收到的原始数据:'.$buf."\n");
- 118 // 自定义协议目的是拿到类方法和参数(可改成自己定义的)
- 119 $this->parseProtocol($buf,$class, $method,$params);
- 120 // 执行方法
- 121 $this->execMethod($client, $class, $method, $params);
- 122 //关闭客户端
- 123 fclose($client);
- 124 echo "关闭了连接\n";
- 125 }
- 126 }
- 127 }
- 128
- 129 /**
- 130 * User: yuzhao
- 131 * CreateTime: 2018/11/16 上午12:19
- 132 * @param $class
- 133 * @param $method
- 134 * @param $params
- 135 * Description: 执行方法
- 136 */
- 137 private function execMethod($client, $class, $method, $params) {
- 138 if($class && $method) {
- 139 // 首字母转为大写
- 140 $class = ucfirst($class);
- 141 $file = $this->params['path'] . '/' . $class . '.php';
- 142 //判断文件是否存在,如果有,则引入文件
- 143 if(file_exists($file)) {
- 144 require_once $file;
- 145 //实例化类,并调用客户端指定的方法
- 146 $obj = new $class();
- 147 //如果有参数,则传入指定参数
- 148 if(!$params) {
- 149 $data = $obj->$method();
- 150 } else {
- 151 $data = $obj->$method($params);
- 152 }
- 153 // 打包数据
- 154 $this->packProtocol($data);
- 155 //把运行后的结果返回给客户端
- 156 fwrite($client, $data);
- 157 }
- 158 } else {
- 159 fwrite($client, 'class or method error');
- 160 }
- 161 }
- 162
- 163 /**
- 164 * User: yuzhao
- 165 * CreateTime: 2018/11/16 上午12:10
- 166 * Description: 解析协议
- 167 */
- 168 private function parseProtocol($buf, &$class, &$method, &$params) {
- 169 $buf = json_decode($buf, true);
- 170 $class = $buf['class'];
- 171 $method = $buf['method'];
- 172 $params = $buf['params'];
- 173 }
- 174
- 175 /**
- 176 * User: yuzhao
- 177 * CreateTime: 2018/11/16 上午12:30
- 178 * @param $data
- 179 * Description: 打包协议
- 180 */
- 181 private function packProtocol(&$data) {
- 182 $data = json_encode($data, JSON_UNESCAPED_UNICODE);
- 183 }
- 184
- 185 }
- 186
- 187 RpcServer::instance([
- 188 'host' => '127.0.0.1',
- 189 'port' => 8888,
- 190 'path' => './api'
- 191 ])->run();
- 1 <?php
- 2 /**
- 3 * User: yuzhao
- 4 * CreateTime: 2018/11/16 上午12:2
- 5 * Description: Rpc客户端
- 6 */
- 7 class RpcClient {
- 8
- 9 /**
- 10 * User: yuzhao
- 11 * CreateTime: 2018/11/16 上午12:21
- 12 * @var array
- 13 * Description: 调用的地址
- 14 */
- 15 private $urlInfo = array();
- 16
- 17 /**
- 18 * RpcClient constructor.
- 19 */
- 20 public function __construct($url)
- 21 {
- 22 $this->urlInfo = parse_url($url);
- 23 }
- 24
- 25 /**
- 26 * User: yuzhao
- 27 * CreateTime: 2018/11/16 上午12:2
- 28 * Description: 返回当前对象
- 29 */
- 30 public static function instance($url) {
- 31 return new RpcClient($url);
- 32 }
- 33
- 34 public function __call($name, $arguments)
- 35 {
- 36 // TODO: Implement __call() method.
- 37 //创建一个客户端
- 38 $client = stream_socket_client("tcp://{$this->urlInfo['host']}:{$this->urlInfo['port']}", $errno, $errstr);
- 39 if (!$client) {
- 40 exit("{$errno} : {$errstr} \n");
- 41 }
- 42 $data = [
- 43 'class' => basename($this->urlInfo['path']),
- 44 'method' => $name,
- 45 'params' => $arguments
- 46 ];
- 47 //向服务端发送我们自定义的协议数据
- 48 fwrite($client, json_encode($data));
- 49 //读取服务端传来的数据
- 50 $data = fread($client, 2048);
- 51 //关闭客户端
- 52 fclose($client);
- 53 return $data;
- 54 }
- 55 }
- 56 $cli = new RpcClient('http://127.0.0.1:8888/test');
- 57 echo $cli->tuzisir1()."\n";
- 58 echo $cli->tuzisir2(array('name' => 'tuzisir', 'age' => 23));
- 1 <?php
- 2 /**
- 3 * User: yuzhao
- 4 * CreateTime: 2018/11/16 上午12:28
- 5 * Description:
- 6 */
- 7
- 8 class Test {
- 9
- 10 public function tuzisir1() {
- 11 return '我是无参方法';
- 12 }
- 13 public function tuzisir2($params) {
- 14 return $params;
- 15 }
- 16 }