博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用PHP来简单的创建一个RPC服务
阅读量:5872 次
发布时间:2019-06-19

本文共 3271 字,大约阅读时间需要 10 分钟。

RPC全称为Remote Procedure Call,翻译过来为"远程过程调用"。主要应用于不同的系统之间的远程通信和相互调用。

比如有两个系统,一个是PHP写的,一个是JAVA写的,而PHP想要调用JAVA中的某个类的某个方法,这时候就需要用到RPC了。

怎么调?直接调是不可能,只能是PHP通过某种自定义协议请求JAVA的服务,JAVA解析该协议,在本地实例化类并调用方法,然后把结果返回给PHP。

 

这里我们用PHP的socket扩展来创建一个服务端和客户端,演示调用过程。

RpcServer.php代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<?php
class 
RpcServer {
    
protected 
$serv 
= null;
 
    
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) {
            
$client 
= stream_socket_accept(
$this
->serv);
 
            
if 
(
$client
) {
                
//这里为了简单,我们一次性读取
                
$buf 
fread
(
$client
, 2048);
                
//解析客户端发送过来的协议
                
$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]);
                    
$file 
$realPath 
'/' 
$class 
'.php'
;
                    
//判断文件是否存在,如果有,则引入文件
                    
if
(
file_exists
(
$file
)) {
                        
require_once 
$file
;
                        
//实例化类,并调用客户端指定的方法
                        
$obj 
new 
$class
();
                        
//如果有参数,则传入指定参数
                        
if
(!
$paramsRet
) {
                            
$data 
$obj
->
$method
[1]();
                        
else 
{
                            
$data 
$obj
->
$method
[1](json_decode(
$params
[1], true));
                        
}
                        
//把运行后的结果返回给客户端
                        
fwrite(
$client
$data
);
                    
}
                
else 
{
                    
fwrite(
$client
'class or method error'
);
                
}
                
//关闭客户端
                
fclose(
$client
);
            
}
        
}
    
}
 
    
public 
function 
__destruct() {
        
fclose(
$this
->serv);
    
}
}
 
new 
RpcServer(
'127.0.0.1'
, 8888, 
'./service'
);

RpcClient.php代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<?php
 
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;
        
//向服务端发送我们自定义的协议数据
        
fwrite(
$client
$proto
);
        
//读取服务端传来的数据
        
$data 
fread
(
$client
, 2048);
        
//关闭客户端
        
fclose(
$client
);
        
return 
$data
;
    
}
}
 
$cli 
new 
RpcClient(
'http://127.0.0.1:8888/test'
);
echo 
$cli
->hehe();
echo 
$cli
->hehe2(
array
(
'name' 
=> 
'test'
'age' 
=> 27));

然后分别运行上面两个脚本(注意,php要添加环境变量)

1
2
> php RpcServer.php
> php RpcClient.php

结果如下:

Test.php代码如下:

1
2
3
4
5
6
7
8
9
<?php
class 
Test {
    
public 
function 
hehe() {
        
return 
'hehe'
;
    
}
    
public 
function 
hehe2(
$params
) {
        
return 
json_encode(
$params
);
    
}
}

目录结构如下:

上面我们自定义的协议,可以随意修改,只要是客户端和服务端两边能够统一并能解析。

客户端通过请求服务端,把要调用的类,方法和参数传递给服务端,服务端去通过实例化调用方法返回结果。

转载于:https://www.cnblogs.com/liliuguang/p/11075685.html

你可能感兴趣的文章
ListView高度
查看>>
某公司机房成功搭建openssh server跳板服务器
查看>>
作业04
查看>>
【公测】智能&便捷&稳定 新版家园只为给你不一样的体验~
查看>>
网页制作工具哪款软件最好?
查看>>
Docker 基础介绍及配置安装 [一]
查看>>
最近的几个学习重点
查看>>
Nginx学习之一:从权威途径(wiki)了解Nginx
查看>>
NO.47 确定项目要完成的需求列表
查看>>
运维人员的解放----Docker快速部署
查看>>
Docker可视化界面(Consul+Shipyard+Swarm+Service Discover
查看>>
MPLS ××× Carrier Supporting Carrier Option AB(二)
查看>>
Iocomp .net仿真仪表控件包
查看>>
zabbix简介及部署
查看>>
(待解决!)jmx在PetClinic中的应用
查看>>
KVC的使用(对一个对象的成员变量进行操作(赋值/取值))
查看>>
企业网站常用中英文对照表
查看>>
android程序中关于webview加载html文件
查看>>
找rpm网站
查看>>
windows下安装whmcs会经常遇到两个问题
查看>>