手写RPC框架实战

文件:

server.php

<?php

class Server {
    public $socket;
    public $class;
    public $method;
    public $param;
    public $serviceDir='service';

    public function __construct($ip,$port) {
        $this->create($ip,$port);
        while(true) {
            $conSock = socket_accept($this->socket);         //接受一个Socket连接
            $protocol = socket_read($conSock,2048);   //读取指定长度的数据
            $this->doProtocol($protocol);
            $file = $this->serviceDir.'/'.$this->class.'.php';
            if(file_exists($file)) {
                require_once $file;
                $obj = new $this->class;
                $method = $this->method;
                $res = $obj->$method($this->param);
            } else {
                $res = $file." not exists!!";
            }
            socket_write($conSock,$res,strlen($res));
            socket_close($conSock);
        }
    }

    // 解读参数
    private function doProtocol($protocol) {
        $data = json_decode($protocol,true);
        $this->class = $data['RPC-CLASS'];
        $this->method = $data['RPC-METHOD'];
        $this->param = json_decode($data['RPC-PARAM']);
    }

    // 创建socket并监听
    private function create($ip,$port) {
        // 产生一个socket,相当于产生一个socket的数据结构
        $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
        // 设置socket选项
        socket_set_option($this->socket,SOL_SOCKET,SO_REUSEADDR,true);
        // 把socket绑定在一个IP地址和端口上
        socket_bind($this->socket,$ip,$port);
        // 监听由指定socket的所有连接
        socket_listen($this->socket);
    }
}
new Server('127.0.0.1',6666);


client.php

<?php

class Client {

    // 地址
    public $host;
    // 调用类名
    public $class;
    // socker连接
    public $socket;
    // 参数
    public $protocol = null;

    public function __construct($url) {
        $url = parse_url($url);
        $this->host = $url['host'];
        $this->port = $url['port'];
        $this->class = basename($url['path']);
        $this->connect();
    }

    // socker 链接
    private function connect() {
        // 产生一个socket,相当于产生一个socket的数据结构
        $this->socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP);
        // 开始一个socket连接
        socket_connect($this->socket,$this->host,$this->port);
    }

    // 方法重载
    public function __call($method,$param) {
        $param = json_encode($param);
        $this->protocol = json_encode([
            'RPC-CLASS' => $this->class,
            'RPC-METHOD' => $method,
            'RPC-PARAM' => $param,
        ]);
        socket_write($this->socket,$this->protocol,strlen($this->protocol)); //写数据到socket缓存
        $data = socket_read($this->socket,2048);                      //读取指定长度的数据
        socket_close($this->socket);                                         //关闭一个socket资源
        return $data;
    }
}


// 远程调用Test.php Test类的 test方法 参数为$param
$param = ['name'=>'lampol','age'=>22];
$client = new Client('http://127.0.0.1:6666/Test');
echo $client->test2($param);
//echo $client->test2($param);
//echo $client->test3($param);

被调用的方法 /service/Test.php

<?php

/**
 * 测试调用类
 * Class Test
 */
class Test
{
    /**
     * 测试调用方法
     * @return string
     */
    public function test1($param)
    {
        $res = [
            'code' => 0,
            'msg' => 'success.test1',
            'data' => $param,
        ];
        return json_encode($res);
    }

    /**
     * 测试调用方法
     * @return string
     */
    public function test2($param)
    {
        $res = [
            'code' => 0,
            'msg' => 'success.test2',
            'data' => $param,
        ];
        return json_encode($res);


    }

    /**
     * 测试调用方法
     * @return string
     */
    public function test3($param)
    {
        $res = [
            'code' => 0,
            'msg' => 'success.test3',
            'data' => $param,
        ];
        return json_encode($res);


    }
}

运行服务端 php server.php

运行客户端 php client.php

麦志建博客
请先登录后发表评论
  • latest comments
  • 总共1条评论
麦志建博客

Connor : 好文

2021-11-17 17:56:30 回复