PHP创建简单RPC服务案例详解

2025-05-27 0 82

RPC 定义

RPC(Remote Procedure Call)即远程过程调用,指被调用方法的具体实现不在程序运行本地,而是在别的某个地方。主要应用于不同的系统之间的远程通信和相互调用。

如 A 调用 B 提供的 remoteAdd 方法:

  1. 首先A与B之间建立一个TCP连接;
  2. 然后A把需要调用的方法名(这里是remoteAdd)以及方法参数(10, 20)序列化成字节流发送出去;
  3. B接受A发送过来的字节流,然后反序列化得到目标方法名,方法参数,接着执行相应的方法调用(可能是localAdd)并把结果30返回;
  4. A接受远程调用结果

有些远程调用选择比较底层的 socket 协议,有些远程调用选择比较上层的 HTTP 协议。

远程调用的好处:

  • 解耦:当方法提供者需要对方法内实现修改时,调用者完全感知不到,不用做任何变更;这种方式在跨部门,跨公司合作的时候经常用到,并且方法的提供者我们通常称为:服务的暴露方

这里使用 PHP Socket 来创建一个服务端和客户端,目录结构如下:

PHP创建简单RPC服务案例详解

服务端

?

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

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76
<?php

class RpcServer {

protected $server = null;

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

{

// 创建一个 Socket 服务

if(($this->server = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) < 0) {

exit("socket_create() 失败的原因是:".socket_strerror($this->server)."\\n");

}

if(($ret = socket_bind($this->server,$host,$port)) < 0) {

exit("socket_bind() 失败的原因是:".socket_strerror($ret)."\\n");

}

if(($ret = socket_listen($this->server,3)) < 0) {

exit("socket_listen() 失败的原因是:".socket_strerror($ret)."\\n");

}

// 判断 RPC 服务目录是否存在

$realPath = realpath(__DIR__ . $path);

if ($realPath === false || !file_exists($realPath)) {

exit("{$path} error \\n");

}

do {

$client = socket_accept($this->server);

if($client) {

// 一次性读取

$buf = socket_read($client, 8024);

echo $buf;

//解析客户端发送过来的协议

$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]);

$method = $method[1];

$params = json_decode($params[1], true);

$file = $realPath . '/' . $class . '.php'; // 类文件需要和类名一致

$data = ''; // 执行结果

// 判断类文件是否存在

if(file_exists($file)) {

// 引入类文件

require_once $file;

// 实例化类

$rfc_obj = new ReflectionClass($class);

// 判断该类指定方法是否存在

if($rfc_obj->hasMethod($method)) {

// 执行类方法

$rfc_method = $rfc_obj->getMethod($method);

$data = $rfc_method->invokeArgs($rfc_obj->newInstance(), [$params]);

} else {

socket_write($client, 'method error');

}

//把运行后的结果返回给客户端

socket_write($client, $data);

}

} else {

socket_write($client, 'class or method error');

}

// 关闭客户端

socket_close($client);

}

}while(true);

}

public function __destruct()

{

socket_close($this->server);

}

}

new RpcServer('127.0.0.1',8080,'./service');

客户端

?

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
<?php

class RpcClient {

protected $client = null;

protected $url_info = []; // 远程调用 URL 组成部分

public function __construct($url)

{

// 解析 URL

$this->url_info = parse_url($url);

}

public function __call($name, $arguments)

{

// 创建一个客户端

$this->client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);

if(!$this->client) {

exit('socket_create() 失败');

}

socket_connect($this->client, $this->url_info['host'], $this->url_info['port']);

// 传递调用的类名

$class = basename($this->url_info['path']);

// 传递调用的参数

$args = '';

if(isset($arguments[0])) {

$args = json_encode($arguments[0]);

}

// 向服务端发送我们自定义的协议数据

$proto = "Rpc-Class: {$class};".PHP_EOL

."Rpc-Method: {$name};".PHP_EOL

."Rpc-Params: {$args};".PHP_EOL;

socket_write($this->client, $proto);

// 读取服务端传来的数据

$buf = socket_read($this->client, 8024);

socket_close($this->client);

return $buf;

}

}

$rpcClient = new RpcClient('http://127.0.0.1:8080/news');

echo $rpcClient->display(['title'=>'txl']);

echo $rpcClient->display(['title'=>'hello world']);

服务类 News

?

1

2

3

4

5

6

7
<?php

class News {

public function display($data)

{

return json_encode(['result'=>"News display(), title is {$data['title']}"]);

}

}

运行测试:

Client

PHP创建简单RPC服务案例详解

Server

PHP创建简单RPC服务案例详解

到此这篇关于PHP创建简单RPC服务案例详解的文章就介绍到这了,更多相关PHP创建简单RPC服务内容请搜索快网idc以前的文章或继续浏览下面的相关文章希望大家以后多多支持快网idc!

原文链接:https://www.cnblogs.com/tangxuliang/p/9718447.html

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

快网idc优惠网 建站教程 PHP创建简单RPC服务案例详解 https://www.kuaiidc.com/70251.html

相关文章

发表评论
暂无评论