AICon 北京站 Keynote 亮点揭秘,想了解 Agent 智能体来就对了! 了解详情
写点什么

快速搭建 Go JSON-RPC Server

  • 2019-09-24
  • 本文字数:1828 字

    阅读完需:约 6 分钟

快速搭建Go JSON-RPC Server

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 nil11}
复制代码

注册 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()1112        if err!= nil{13            log.Fatalln("accept failed:",err)14        }1516        fmt.Println("jsonrpc server  start lisen on 11223...")171819        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) {1011        $err = fwrite($this->conn, json_encode([12            'method' => $method,13            'params' => array($params),14            'id' => 1,15        ]));1617        if (empty($err)) {18            return false;19        }2021        stream_set_timeout($this->conn, 0, 300);2223        $line = fgets($this->conn);24        if ($line === false) {25            return NULL;26        }2728        fclose($this->conn);2930        return json_decode($line, true);31    }32}3334$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] = x4    return json.Unmarshal(*c.req.Params, &params)5    ...
复制代码


通过这个坑发现,Go jsonrpc 并未严格按照 JSON-RPC 规范实现。

内部处理流程


作者介绍:


作者张大辉(企业代号名),目前负责贝壳找房 PHP、GO 方向研发工作。


本文转载自公众号贝壳产品技术(ID:gh_9afeb423f390)。


原文链接:


https://mp.weixin.qq.com/s/k0cQ_kIs4FhfAz_ncctRBg


2019-09-24 18:152228

评论 1 条评论

发布
用户头像
Go 的 net/rpc/jsonrpc 只实现了 JSON-RPC 1.0 规范,在 JSON-RPC 1.0 规范中请求的 params 只能是 JSON Array。
https://stackoverflow.com/questions/24404108/json-rpc-parameters-version-1-0-vs-2-0
2021-02-23 10:04
回复
没有更多了
发现更多内容

网络攻防学习笔记 Day133

穿过生命散发芬芳

网络基础 9月日更

深入理解 Java 多线程核心知识:跳槽面试必备,Java算法基础面试题

Java 程序员 后端

三分钟带你入门-redis-高可用架构之哨兵,大厂Java高级面试题汇总解答

Java 程序员 后端

翻转未来!钢铁之城重添色彩

白洞计划

Vue进阶(幺零八):npm run build 错误 (node:7852) UnhandledPromiseRejectionWarning: CssSyntaxError:xxxx. 解决分析

No Silver Bullet

Vue 9月日更

写给互联网工程师的5G书 | 0. 前言

俞凡

架构 5G

深入理解Java中的不可变对象,这可能是目前最全的

Java 程序员 后端

深入理解Java虚拟机-虚拟机执行子系统,字节跳动超高难度三面java程序员面经

Java 程序员 后端

HTML进阶(三)

Augus

html 9月日更

分享 4 个前端开发必备的 Chrome 扩展

devpoint

SVG chrome扩展 9月日更

写给互联网工程师的5G书 | 1. 简介

俞凡

架构 5G

全方位解读服务网格(Service Mesh)的背景和概念

xcbeyond

Service Mesh 服务网格 引航计划

Context 和 struct

Rayjun

struct Context Go 语言

手撸二叉树之二叉搜索树中的众数

HelloWorld杰少

9月日更

服务注册与发现的原理和实现

万俊峰Kevin

微服务 服务注册与发现 microservice 服务发现 Go 语言

【LeetCode】有效的括号字符串Java题解

Albert

算法 LeetCode 9月日更

模块七作业

seawolflin

架构实战营

常用特殊符号大全

入门小站

工具

深入理解Java中的不可变对象(1),面试加分项

Java 程序员 后端

【Flutter 专题】49 图解 Flutter 与 Android 原生交互

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9月日更

双指针算法之同向双指针

泽睿

Java 数据结构 面试 双指针算法

Parted 创建 GPT 分区

耳东@Erdong

Linux 9月日更 parted 磁盘分区

Redis核心原理与实践--列表实现原理之ziplist结构

binecy

redis 源码分析

一名优秀的技术Leader是如何炼成的?

架构精进之路

管理 技术管理 引航计划 内容合集

数据结构和算法应用

Albert

算法 9月日更

linux之chsh命令

入门小站

Linux

Golang 中的好代码 VS 烂代码

baiyutang

编码 Go 语言 9月日更

科技的进步会造福人类吗--闲聊科幻

姬翔

9月日更

OpenSL ES

Changing Lin

9月日更

【网络安全】Spring框架漏洞总结(二)

网络安全学海

黑客 网络安全 信息安全 WEB安全 漏洞挖掘

为何数据类大项目都会先做盘点??

奔向架构师

数据仓库 数据治理 9月日更

快速搭建Go JSON-RPC Server_文化 & 方法_张大辉_InfoQ精选文章