golang实现rpc方法二:使用jsonrpc库【跨平台】

首先在golang实现rpc方法一net/rpc库中实现了RPC方法,但是那个方法不是跨平台的,没法在其他语言中调用这个实现的RPC方法,接下来我们可以通过jsonroc库实现跨语言的RPC方法。俩种实现方式的代码其实也是差不多的,大差不差,只是调用的库不同。

项目左侧包结构

rpc服务端

serverrpc.go实现代码如下

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 //product 表示乘积
	Quo int //quotient 表示商
	Rem int //remaind 表示余数
}

/*
运算结构体的乘法运算方法
第一个参数只需要拿到其里面的值只需要传一个结构体即可,
第二个参数需要将运算结果存到其里面所以需要传地址
*/
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 { //除法为0,运算不合法
		return errors.New("divide by zero")
	}
	res.Quo = req.A / req.B
	res.Rem = req.A % req.B
	return nil
}
func main() {
	rpc.Register(new(Arith)) //注册rpc服务

	lis, err := net.Listen("tcp", "127.0.0.1:8090") //Listen是block(阻塞的)
	if err != nil {
		log.Fatalln("fatal error:", err)
	}
	fmt.Fprintf(os.Stdout, "%s", "start connection")

	//写了一个循环里面启动了一个协程可以处理多个协程
	for {
		conn, err := lis.Accept() //接收客户端连接请求
		if err != nil {  //当前请求存在错误,跳过当前请求
			continue
		}

		//启动一个协程并发处理请求
		go func(conn net.Conn) {
			fmt.Fprintf(os.Stdout, "%s", "new client is coming\n")
			jsonrpc.ServeConn(conn)
		}(conn) //自己调用自己
	}
}

rpc客户端

clientrpc.go实现代码如下

Go 复制代码
package main

import (
	"fmt"
	"log"
	"net/rpc/jsonrpc"
)

// 算数运算请求结构体
type ArithRequest struct {
	A int
	B int
}

// 算数运算响应结构体
type ArithResponse struct {
	Pro int //product 乘积
	Quo int //quotient 商
	Rem int //remain 余数
}

func main() {
	//通过jsonrpc库实现
	conn, err := jsonrpc.Dial("tcp", "127.0.0.1:8090")
	if err != nil {
		log.Fatalln("dailing error", err)
	}

	req := ArithRequest{9, 2} //请求结构体
	var res ArithResponse     //响应结构体,用于存储运算结果

	//实现jsonrpc之后,通过Call方法在客户端调用服务端里面算数运算结构体的乘法运算方法
	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)

	//实现jsonrpc之后,通过Call方法在客户端调用服务端里面算数运算结构体的除法运算方法
	err = conn.Call("Arith.Divide", req, &res)
	if err != nil {
		log.Fatalln("arith error", err)
	}
	fmt.Printf("%d / %d, quo is %d, rem is %d\n", req.A, req.B, res.Quo, res.Rem)
}

详细实现步骤

1.首先初始化项目

bash 复制代码
go mod init pro01  //pro01表示项目名称

2.在当前项目下新建包server,并且在该包下面新建serverrpc.go实现rpc服务端

3.在当前项目下新建包client,并且在该包下面新建clientrpc.go实现rpc客户端

4.运行rpc服务端程序 ,首先进入server包,然后运行serverrpc.go

bash 复制代码
cd server
go run serverrpc.go

5.运行rpc客户端程序,首先进入client包,然后运行clientrpc.go

bash 复制代码
cd client
go run clientrpc.go

6.查看输出结果是否正确,输出结果如下表示程序运行结果正确,当然我这里的结果是根据我在请求结构体里面给出的俩个数值进行计算的,具体结果是否正确根据自己的具体程序判断。

常见错误

如果启动rpc服务时出现了如下图所示错误,说明在之前已经启动过rpc服务,并且没有关闭,导致端口被占用了,只需要把之前启动的程序停掉,然后重新启动rpc服务即可。

总结:

jsonrpc库和net/rpc都实现了rpc方法,实现了远程进程调用,区别在于net/rpc是不跨平台的,别的语言没法调用,而jsonrpc是跨平台的,别的语言也可以调用rpc方法。

相关推荐
Am心若依旧40932 分钟前
[c++11(二)]Lambda表达式和Function包装器及bind函数
开发语言·c++
明月看潮生34 分钟前
青少年编程与数学 02-004 Go语言Web编程 20课题、单元测试
开发语言·青少年编程·单元测试·编程与数学·goweb
大G哥44 分钟前
java提高正则处理效率
java·开发语言
VBA63371 小时前
VBA技术资料MF243:利用第三方软件复制PDF数据到EXCEL
开发语言
轩辰~1 小时前
网络协议入门
linux·服务器·开发语言·网络·arm开发·c++·网络协议
小_太_阳1 小时前
Scala_【1】概述
开发语言·后端·scala·intellij-idea
向宇it1 小时前
【从零开始入门unity游戏开发之——unity篇02】unity6基础入门——软件下载安装、Unity Hub配置、安装unity编辑器、许可证管理
开发语言·unity·c#·编辑器·游戏引擎
古希腊掌管学习的神2 小时前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师2 小时前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
就爱学编程2 小时前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法