【golang/jsonrpc】go-ethereum中json rpc初步使用(websocket版本)

说在前面

  • 操作系统:win11 wsl2
  • go-ethereum版本:1.15.8

关于json-rpc

server

  • 定义方法

    go 复制代码
    type CalculatorService struct{}
    
    func (s *CalculatorService) Add(a, b int) int {
    	return a + b
    }
    
    func (s *CalculatorService) Div(a, b int) (int, error) {
    	if b == 0 {
    		return 0, errors.New("divide by zero")
    	}
    	return a / b, nil
    }

    这里我们简单定义两个方法

  • 启动服务

    go 复制代码
    func main() {
    	calculator := new(CalculatorService)
    
    	// 创建 RPC 服务器
    	rpcServer := rpc.NewServer()
    
    	// 注册服务
    	if err := rpcServer.RegisterName("calculator", calculator); err != nil {
    		panic(err)
    	}
    
    	// 启动 HTTP 服务器
    	println("WebSocket server listening on :8080")
    
    	httpHandler := rpcServer.WebsocketHandler([]string{"*"})
    	http.Handle("/ws", httpHandler)
    
    	http.ListenAndServe(":8080", nil)
    }

client

  • 调用
    在调用的时候,方法名需要指定为receiver_method,例如我们要调用CalculatorService.Add,那么调用名为calculator_add,注意,这里的calculator为server端注册时的RegisterName("calculator", calculator),而不是CalculatorService

    go 复制代码
    func main() {
    	// 连接 WebSocket 服务端
    	client, err := rpc.DialWebsocket(context.Background(), "ws://192.168.1.6:8080/ws", "")
    	if err != nil {
    		panic(err)
    	}
    	defer client.Close()
    
    	// 调用远程方法
    	var result int
    	err = client.Call(&result, "calculator_add", 3, 5)
    	if err != nil {
    		panic(err)
    	}
    
    	fmt.Println("Result:", result) // 输出: Result: 8
    }

    假设将server端的RegisterName("calculator", calculator)改为RegisterName("calculate", calculator)

    shell 复制代码
    panic: the method calculator_add does not exist/is not available

注意事项

返回值

  • server端的方法返回值只能有三种数量0,1,2

    • 0,即无返回值
    • 1,即自定义返回值或者一个error
    • 2,即自定义返回值+一个error
  • 这样,在client端调用的时候,err = client.Call(&result, "calculator_add", 3, 5)result对应自定义返回值,err对应返回的error

  • 例如,我们调用

    go 复制代码
    err = client.Call(&result, "calculate_div", 3, 0)
    if err != nil {
    	panic(err)
    }

    得到的err即为server端Div方法返回的error

    shell 复制代码
    panic: divide by zero

server端调用client端

  • 支持反向调用

  • 在我们定义server端方法的时候,可以增加一个context参数

    go 复制代码
    type CalculatorService struct{}
    
    func (s *CalculatorService) Add(ctx context.Context, a, b int) int {
    	return a + b
    }
    
    func (s *CalculatorService) Div(ctx context.Context, a, b int) (int, error) {
    	if b == 0 {
    		return 0, errors.New("divide by zero")
    	}
    	return a / b, nil
    }
  • 这样我们就可以获取到client,进而调用其方法,例如,我们在client端添加一个方法

    go 复制代码
    type CalcService struct{}
    
    func (s *CalcService) GetParam(ctx context.Context) int {
    	return 88
    }

    然后在client端注册

    go 复制代码
    func main() {
    	// 连接 WebSocket 服务端
    	client, err := rpc.DialWebsocket(context.Background(), "ws://192.168.1.6:8080/ws", "")
    	if err != nil {
    		panic(err)
    	}
    	defer client.Close()
    
    	calculator := new(CalcService)
    	client.RegisterName("calc", calculator)
    
    	// 调用远程方法
    	var result int
    	err = client.Call(&result, "calculate_add", 3, 0)
    	if err != nil {
    		panic(err)
    	}
    
    	fmt.Println("Result:", result) // 输出: Result: 8
    }

    在server端的Add方法中,我们将b的值改为从client端获取

    shell 复制代码
    func (s *CalcService) Add(ctx context.Context, a, b int) int {
    	client, ok := rpc.ClientFromContext(ctx)
    	if ok {
    		client.Call(&b, "calc_getParam")
    	}
    	return a + b
    }

    这样运行后的结果为:

    shell 复制代码
    Result: 91
  • 通过这种方式,我们可以在server端添加一个Register的方法,在client连接后,client主动调用Register方法,这样我们就可以管理所有client了

相关推荐
争不过朝夕,又念着往昔1 小时前
Go语言反射机制详解
开发语言·后端·golang
Jerry Lau1 小时前
go go go 出发咯 - go web开发入门系列(二) Gin 框架实战指南
前端·golang·gin
二DUAN帝1 小时前
UE实现路径回放、自动驾驶功能简记
人工智能·websocket·机器学习·ue5·自动驾驶·ue4·cesiumforue
2501_915918413 小时前
iPhone 抓包工具有哪些?多工具对比分析优缺点
websocket·网络协议·tcp/ip·http·网络安全·https·udp
游戏开发爱好者87 小时前
iOS 出海 App 安全加固指南:无源码环境下的 IPA 加固与防破解方法
websocket·网络协议·tcp/ip·http·网络安全·https·udp
2501_915921437 小时前
苹果App上架流程:不用Mac也可以上架的方法
websocket·网络协议·tcp/ip·http·网络安全·https·udp
paopaokaka_luck8 小时前
智能推荐社交分享小程序(websocket即时通讯、协同过滤算法、时间衰减因子模型、热度得分算法)
数据库·vue.js·spring boot·后端·websocket·小程序
沐尘而生9 小时前
【AI智能体】智能音视频-硬件设备基于 WebSocket 实现语音交互
大数据·人工智能·websocket·机器学习·ai作画·音视频·娱乐
witton10 小时前
Go语言网络游戏服务器模块化编程
服务器·开发语言·游戏·golang·origin·模块化·耦合
叹一曲当时只道是寻常10 小时前
Softhub软件下载站实战开发(十六):仪表盘前端设计与实现
前端·golang