jsonrpc 是无状态、轻量级的远程过程调用协议,传递数据格式为 JSON。GO 官方提供 rpc 包和 jsonrpc 包,与 rpc 包不同的是,jsonrpc 可以实现跨平台通信。本文将介绍如何用 Go 快速搭建一个 jsonrpc Server,用 PHP 实现 jsonrpc client 进行验证,同时也记录下验证过程中出现的坑。
实现 jsonrpc_server
引入包
1import (
2 "net/rpc"
3 "net"
4 "log"
5 "net/rpc/jsonrpc"
6 "fmt"
7)
定义 server 端要伺服的 rpc method
1// rpc handler
2type Edwin int
3// 定义rpc method 第一个参数是请求对象,第二参数是返回对象,返回值是返回rpc 内部调用过程中出现的错误信息
4func (this *Edwin) Add(args map[string]float64,res *float64) error {
5 *res = args["num1"] + args["num2"]
6 return nil
7}
8func (this *Edwin) Multi(args map[string]interface{},res *float64) error {
9 *res = args["num1"].(float64) * args["num2"].(float64)
10 return nil
11}
注册 rpc handler,开启 server connection
1 rpc.Register(new(Edwin))
2
3 l,err := net.Listen("tcp",":11223")
4
5 if err!=nil{
6 log.Fatalln("listen error:",err)
7 }
8
9 for{
10 conn,err := l.Accept()
11
12 if err!= nil{
13 log.Fatalln("accept failed:",err)
14 }
15
16 fmt.Println("jsonrpc server start lisen on 11223...")
17
18
19 go func(conn net.Conn) {
20 fmt.Println("a new connection is coming...")
21 jsonrpc.ServeConn(conn)
22 }(conn)
23 }
php 实现 jsonrpc_client
1class JsonRpc {
2 private $conn;
3
4 function __construct($host, $port) {
5 $this->conn = fsockopen($host, $port, $errno, $errStr, 2);
6
7 }
8
9 public function call($method, $params) {
10
11 $err = fwrite($this->conn, json_encode([
12 'method' => $method,
13 'params' => array($params),
14 'id' => 1,
15 ]));
16
17 if (empty($err)) {
18 return false;
19 }
20
21 stream_set_timeout($this->conn, 0, 300);
22
23 $line = fgets($this->conn);
24 if ($line === false) {
25 return NULL;
26 }
27
28 fclose($this->conn);
29
30 return json_decode($line, true);
31 }
32}
33
34$client = new JsonRPC("127.0.0.1", 11223);
35$client2 = new JsonRPC("127.0.0.1", 11223);
36$ret = $client->Call("Edwin2.Multi", array("num1" => 14, "num2" => 20));
37$ret2 = $client2->Call("Edwin2.Add", array("num1" => 14, "num2" => 20));
38var_export($ret);
39var_export($ret2);
验证
1# 开启 jsonrpc server
2go run jsonrpc_server.go
3# 正常会输出监听信息
4> jsonrpc server start lisen on 11223...
5> a new connection is coming...
6# 执行 jsonrpc client
7php jsonrpc_clinent.php
8# 正常输出以下信息
9> array (
10 'id' => 1,
11 'result' => 280,
12 'error' => NULL,
13)array (
14 'id' => 1,
15 'result' => 34,
16 'error' => NULL,
17)
验证中的问题
问题代码:
1$err = fwrite($this->conn, json_encode([
2 'method' => $method,
3 'params' => array($params),
4 // 'params' => $params // 不能这么用
5 'id' => 1,
6 ]));
params 参数必须用 array 包含,如果直接传递过去,将报出以下错误信息:
1array (
2 'id' => 1,
3 'result' => NULL,
4 'error' => 'json: cannot unmarshal object into Go value of type [1]interface {}',
5)
根据 JSON-RPC 规范,参数 params 可以是 Json Array,也可以是 Json Object,可是为什么还报错呢?于是查看源码,发现:
1在 src/net/rpc/jsonrpc/server.go 第95行,go官方实现指定params必须是数组:
2 var params [1]interface{}
3 params[0] = x
4 return json.Unmarshal(*c.req.Params, ¶ms)
5 ...
通过这个坑发现,Go jsonrpc 并未严格按照 JSON-RPC 规范实现。
内部处理流程
作者介绍:
作者张大辉(企业代号名),目前负责贝壳找房 PHP、GO 方向研发工作。
本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。
原文链接:
https://mp.weixin.qq.com/s/k0cQ_kIs4FhfAz_ncctRBg
更多内容推荐
盘点 2021 征文大赛获奖名单公布!
盘点 2021 征文大赛获奖名单公布!
2022-01-19
Qt|编辑框的使用总结
QLineEdit、QTextEdit、QPlainTextEdit、QTextBrowser
2022-07-22
分布式协议 -Paxos
client(客户端)向 proposer(提议者)发起一个 proposal(提案),由 proposer向 acceptor(接受者)进行提议
2022-05-23
手把手教大家在 gRPC 中使用 JWT 完成身份校验
@[toc]上篇文章松哥和小伙伴们聊了在 gRPC 中如何使用拦截器,这些拦截器有服务端拦截器也有客户端拦截器,这些拦截器的一个重要使用场景,就是可以进行身份的校验。当客户端发起请求的时候,服务端通过拦截器进行身份校验,就知道这个请求是谁发起的了。今天
2023-02-22
加餐|GPT 编程(下) :如何利用 OpenAI 的 API 解决语言处理类任务?
如何利用OpenAI的API解决语言处理类任务?
2023-05-15
木兰汇专访 | 网心科技联合创始人马婷:创业者的“长期主义”
近日,又一位商界木兰加入中国企业家木兰汇大家庭,她是迅雷集团高级副总裁、网心科技联合创始人、首席运营官马婷。
2023-05-05
2022 亚洲国际物联网展会
2022亚洲国际物联网展会
2022-07-21
启新聚势 云谱新篇|海泰方圆与四川联通达成生态战略合作
7月15日,“启新聚势 云谱新篇” 联通云巡展(四川站)暨生态合作伙伴大会盛大举办。大会上,作为中国联合网络通信有限公司四川省分公司(简称四川联通)的生态合作伙伴,海泰方圆与四川联通签署了生态战略合作协议,双方将以联通云为新起点,携手打造标准化
2022-07-19
康威定律如何解释微服务的合理性
微服务这个概念很早就提出了, 真正火起来是在2016年左右,而康威定律(Conway's Law)就是微服务理论基础。
2022-07-09
34.Dubbo Provider & Consumer 案例搭建
2023-09-29
1. Context 简介
2023-09-26
21|Web 开发(上):如何使用 Axum 框架进行 Web 后端开发?
如何使用Axum框架进行Web后端开发?
2023-12-11
直播 APP 开发,协议盘点(五):实时传输协议 RTP
简单搭建实时传输协议RTP的部分参考代码: import socket rtp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) rtp_port = 1234 rtp_socket.bind(('localhost', rtp_port)) packet_size = 1024
2023-08-23
23. 行为型 - 模板方法 Template Method
2023-02-15
LED 显示屏与 LCD 拼接屏的对比
LED显示屏又叫电子显示屏,是由LED点阵和LED pc面板组成,通过红色,蓝色,白色,绿色LED灯的亮灭来显示文字、图片、动画、视频,内容的显示屏幕。
2023-03-15
跨平台应用开发进阶 (三十六) :uniapp 使用 uni.request 请求报错{“errMsg“:“request:fail abort statusCode:-1“}的解决办法
在uniapp中,使用uni.request()向服务端接口发起请求后,返回值为:{"errMsg":"request:fail abort statusCode:-1"},因此,导致了后面的业务代码报错。
2022-12-22
ESP32-C3 学习测试 蓝牙 篇(三、认识蓝牙 GATT 协议)
本文带小白认识一下 蓝牙 GATT 协议
2022-09-29
Qt | 关于目录操作的使用 QDir
Qt关于目录操作的使用 QDir。
2022-09-07
DPU 厂商北中网芯加入龙蜥社区,共建网络通信与安全
近日,成都北中网芯科技有限公司(以下简称“北中网芯”)签署了CLA(Contributor License Agreement,贡献者许可协议),正式加入龙蜥社区(OpenAnolis)。
2023-03-24
34|WebSocket:如何在消息队列内核中支持 WebSocket?
WebSocket 是一种实时协议,它在单个 TCP 连接上提供持久的全双工通信。
2023-09-06
推荐阅读
03|动态 Response:按照规范构造返回流
2023-12-13
macOS 14 Sonoma 14.1.1 正式版 (最新苹果系统) pkg 完整安装包
2023-11-08
22|Web 开发(下):如何实现一个 Todo List 应用?
2023-12-13
SnailSVN Pro for mac(SVN 客户端)v1.10 永久激活版
2023-10-30
Studio One 6 for mac(音乐制作工具) v6.2.0 完整激活版
2023-10-22
对话在行人|合众思壮:基于用友 BIP 重塑业务应用,推进业财融合
2023-11-06
02|初出茅庐:构造一个极简的 HttpServer
2023-12-11
电子书
大厂实战PPT下载
换一换 杨子奇 | 火山引擎 边缘云高级项目经理
俞育才 | eBay 特征平台负责人
邵迪 | vivo 互联网算法总监
评论 1 条评论