|
快速搭建Go JSON-RPC Server
快速搭建Go JSON-RPC Server
张大辉
贝壳产品技术
贝壳产品技术 “贝壳产品技术公众号”作为贝壳官方产品技术号,致力打造贝壳产品、技术干货分享平台,面向互联网/O2O开发/产品从业者,每周推送优质产品技术文章、技术沙龙活动及招聘信息等。欢迎大家关注我们。 242篇内容
2018年11月02日 20:00
作者张大辉(企业代号名),目前负责贝壳找房PHP、GO方向研发工作。1前言jsonrpc是无状态、轻量级的远程过程调用协议,传递数据格式为JSON。GO 官方提供rpc包和jsonrpc包,与rpc包不同的是,jsonrpc可以实现跨平台通信。本文将介绍如何用Go快速搭建一个jsonrpc Server,用PHP实现jsonrpc client进行验证,同时也记录下验证过程中出现的坑。2实现jsonrpc_server2.1 引入包1import(2"net/rpc"3"net"4"log"5"net/rpc/jsonrpc"6"fmt"7)2.2 定义 server端要伺服的 rpc method 1//rpchandler 2typeEdwinint 3//定义rpcmethod第一个参数是请求对象,第二参数是返回对象,返回值是返回rpc内部调用过程中出现的错误信息 4func(this*Edwin)Add(argsmap[string]float64,res*float64)error{ 5*res=args["num1"]+args["num2"] 6returnnil 7} 8func(this*Edwin)Multi(argsmap[string]interface{},res*float64)error{ 9*res=args["num1"].(float64)*args["num2"].(float64)10returnnil11}2.3 注册rpc handler,开启server connection 1rpc.Register(new(Edwin)) 2 3l,err:=net.Listen("tcp",":11223") 4 5iferr!=nil{ 6log.Fatalln("listenerror:",err) 7} 8 9for{10conn,err:=l.Accept()1112iferr!=nil{13log.Fatalln("acceptfailed:",err)14}1516fmt.Println("jsonrpcserverstartlisenon11223...")171819gofunc(connnet.Conn){20fmt.Println("anewconnectioniscoming...")21jsonrpc.ServeConn(conn)22}(conn)23}3php实现jsonrpc_client 1classJsonRpc{ 2private$conn; 3 4function__construct($host,$port){ 5$this->conn=fsockopen($host,$port,$errno,$errStr,2); 6 7} 8 9publicfunctioncall($method,$params){1011$err=fwrite($this->conn,json_encode([12'method'=>$method,13'params'=>array($params),14'id'=>1,15]));1617if(empty($err)){18returnfalse;19}2021stream_set_timeout($this->conn,0,300);2223$line=fgets($this->conn);24if($line===false){25returnNULL;26}2728fclose($this->conn);2930returnjson_decode($line,true);31}32}3334$client=newJsonRPC("127.0.0.1",11223);35$client2=newJsonRPC("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);4验证 1#开启jsonrpcserver 2gorunjsonrpc_server.go 3#正常会输出监听信息 4>jsonrpcserverstartlisenon11223... 5>anewconnectioniscoming... 6#执行jsonrpcclient 7phpjsonrpc_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)5验证中的问题问题代码: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:cannotunmarshalobjectintoGovalueoftype[1]interface{}',5)根据JSON-RPC规范,参数params可以是Json Array,也可以是Json Object,可是为什么还报错呢?于是查看源码,发现:1在src/net/rpc/jsonrpc/server.go第95行,go官方实现指定params必须是数组:2varparams[1]interface{}3params[0]=x4returnjson.Unmarshal(*c.req.Params,¶ms)5...通过这个坑发现,Go jsonrpc并未严格按照JSON-RPC规范实现。6内部处理流程
预览时标签不可点
阅读原文关闭更多小程序广告搜索「undefined」网络结果
阅读原文
|
|