RPC全称为Remote Procedure Call,翻译过来为"远程过程调用"。主要应用于不同的系统之间的远程通信和相互调用。
文件结构
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} \n");
}
//RPC服务目录是否存在
$realPath = realpath(__DIR__ . $path);
if ($realPath === false || !file_exists($realPath)) {
exit("{$path} error \n");
}
//解析数据,执行业务逻辑
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')."\t"."[$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 \n");
}
}
/**
* 远程调用
* @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} \n");
}
//采用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端
启动client端测试
要设计一个rpc框架,要做的不仅仅如此,大家个参考其他rpc框架
持续更新~