RPC
就是因为无法在同一个进程内,或者无法在同一个服务器上通过本地调用的方式实现我们的需求。HTTP能满足需求但是不够高效,所以我们需要使用RPC。
rpc_service.go
package main
import (
"errors"
"fmt"
"log"
"net"
"net/http"
"net/rpc"
"os"
)
type Arith struct {
}
//请求结构体
type ArithRequest struct {
A int
B int
}
//响应结构体
type ArithResponse struct {
Pro int //乘积
Quo int //商
Rem int //余数
}
//乘积方法
func (this *Arith) Multiply(req ArithRequest,res *ArithResponse) error{
res.Pro = req.A * req.B
return nil
}
//除法运算方法
func (this *Arith) Divide(req ArithRequest,res *ArithResponse) error{
if req.B ==0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}
func main() {
//注册rpc服务
rpc.Register(new(Arith))
//采用http协议作为rpc载体
rpc.HandleHTTP()
lis,err := net.Listen("tcp","127.0.0.1:8095")
if err!=nil {
log.Fatalln("fatal error:",err)
}
fmt.Fprintf(os.Stdout,"%s","start connection\n")
//常规启动http服务
http.Serve(lis,nil)
}
复制代码
rpc_client.go
package main
import (
"fmt"
"log"
"net/rpc"
)
//算数运算请求结构体
type ArithRequest struct {
A int
B int
}
//响应结构体
type ArithResponse struct {
Pro int //乘
Quo int //商
Rem int //余数
}
func main() {
conn,err := rpc.DialHTTP("tcp","127.0.0.1:8095")
if err!=nil {
log.Fatalln("dialing error:",err)
}
req := ArithRequest{10,20}
var res ArithResponse
err = conn.Call("Arith.Multiply",req,&res) //乘法运算
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d * %d = %d\n",req.A,req.B,res.Pro)
//除法运算
err = conn.Call("Arith.Divide",req,&res)
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d / %d = %d 余数是:%d",req.A,req.B,res.Quo,res.Rem)
}
复制代码
//服务端console
start connection
//客户端console
10 * 20 = 200
10 / 20 = 0 余数是:10
复制代码
jsonrpc_server.go
package main
import (
"errors"
"fmt"
"log"
"net"
"net/rpc"
"net/rpc/jsonrpc"
"os"
)
type Arith struct {
}
//请求结构体
type ArithRequest struct {
A int
B int
}
//响应结构体
type ArithResponse struct {
Pro int //乘积
Quo int //商
Rem int //余数
}
//乘积方法
func (this *Arith) Multiply(req ArithRequest,res *ArithResponse) error{
res.Pro = req.A * req.B
return nil
}
//除法运算方法
func (this *Arith) Divide(req ArithRequest,res *ArithResponse) error{
if req.B ==0 {
return errors.New("divide by zero")
}
res.Quo = req.A / req.B
res.Rem = req.A % req.B
return nil
}
func main() {
//注册rpc服务
rpc.Register(new(Arith))
//采用http协议作为rpc载体
rpc.HandleHTTP()
lis,err := net.Listen("tcp","127.0.0.1:8096")
if err!=nil {
log.Fatalln("fatal error:",err)
}
fmt.Fprintf(os.Stdout,"%s","start connection\n")
//接收客户端请求 并发处理 jsonrpc
for {
conn,err :=lis.Accept() //接收客户端连接请求
if err!=nil {
continue
}
//并发处理客户端请求
go func(conn net.Conn) {
fmt.Fprintf(os.Stdout,"%s","new client in coming\n")
jsonrpc.ServeConn(conn)
}(conn)
}
//常规启动http服务
//http.Serve(lis,nil)
}
复制代码
jsonrpc_client.go
package main
import (
"fmt"
"log"
"net/rpc/jsonrpc"
)
//算数运算请求结构体
type ArithRequest struct {
A int
B int
}
//响应结构体
type ArithResponse struct {
Pro int //乘
Quo int //商
Rem int //余数
}
func main() {
// 只有这里不一样
conn,err := jsonrpc.Dial("tcp","127.0.0.1:8096")
if err!=nil {
log.Fatalln("dialing error:",err)
}
req := ArithRequest{9,2}
var res ArithResponse
err = conn.Call("Arith.Multiply",req,&res) //乘法运算
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d * %d = %d\n",req.A,req.B,res.Pro)
//除法运算
err = conn.Call("Arith.Divide",req,&res)
if err!=nil {
log.Fatalln("arith error:",err)
}
fmt.Printf("%d / %d = %d 余数是:%d",req.A,req.B,res.Quo,res.Rem)
}
复制代码
//服务端console
start connection
//客户端console
9 * 2 = 18
9 / 2 = 4 余数是:1
//服务端console
new client in coming
复制代码
jsonrpc_server.go:和入门2服务端的代码一样
jsonrpc_client.php
<?php
class JsonRPC
{
private $conn;
function __construct($host, $port)
{
$this->conn = fsockopen($host, $port, $errno, $errstr, 3);
if (!$this->conn) {
return false;
}
}
public function Call($method, $params)
{
if (!$this->conn) {
return false;
}
$err = fwrite($this->conn, json_encode(array(
'method' => $method,
'params' => array($params),
'id' => 0,
)) . "\n");
if ($err === false) {
return false;
}
stream_set_timeout($this->conn, 0, 3000);
$line = fgets($this->conn);
if ($line === false) {
return NULL;
}
return json_decode($line, true);
}
}
$client = new JsonRPC("127.0.0.1", 8096);
$args = array('A' => 9, 'B' => 2);
$r = $client->Call("Arith.Multiply", $args);
printf("%d * %d = %d\n", $args['A'], $args['B'], $r['result']['Pro']);
$r = $client->Call("Arith.Divide", array('A' => 9, 'B' => 2));
printf("%d / %d, Quo is %d, Rem is %d\n", $args['A'], $args['B'], $r['result']['Quo'], $r['result']['Rem']);
复制代码
如何在本地启动PHP
//本地启动PHP服务:http://127.0.0.1/jsonrpc_client.php,运行结果如下:
9 * 2 = 18 9 / 2, Quo is 4, Rem is 1
复制代码
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有