java 调用golang_golang与java间的json-rpc跨语言调用

弘思聪
2023-12-01

关于如何使用golang进行json-rpc的调用,网上虽然有很多的帖子,但都仅仅是golang程序间通信,没有牵涉到跨语言调用的问题。在使用golang开发服务端程序的时候,不可避免的要与其他语言的程序进行交互,特别是json-rpc这的协议,本身就应该是用在不同的平台间的调用上的(因为golang程序间的交流已经有了封闭的用gob编码解码的rpc包了,我们自然而言的会想到用json-rpc来提供对其他语言的支持)。本文就来详细探究一下如何实现golang与java之间的json-rpc调用。转载请注明出处:http://www.cnblogs.com/geomantic/p/4751859.html

首先,实现一个基于socket的java调用golang的样例(这个方法不需要第三方golang库,因为golang本身就有jsonrpc的支持库,但是仅能通过tcp协议通信,并且有一些格式上的局限,直接与其他的语言交互会有些障碍。如果要通过http协议通信的话,必须自己写一个或者用第三方的库,后面会有介绍)

package rpcz//first we create a simple golang rpc server based on socket

import ("fmt"

"net"

"net/rpc"

"net/rpc/jsonrpc")

type Counterstruct{

Sumint}

func (this *Counter) Add(i int, r *int) error {this.Sum +=i*r = this.Sum

fmt.Printf("i: %v", i)returnnil

}

func NewJsonRpcSocketServer() {

rpc.Register(new(Counter))

l, err := net.Listen("tcp", ":3333")if err !=nil {

fmt.Printf("Listener tcp err: %s", err)return}for{

fmt.Println("wating...")

conn, err :=l.Accept()if err !=nil {

fmt.Sprintf("accept connection err: %s\n", conn)

}

go jsonrpc.ServeConn(conn)

}

}

func NewJsonRpcSocketClient() {

conn, err := net.DialTimeout("tcp", "127.0.0.1:3333", 1000*1000*1000*30)if err !=nil {

fmt.Printf("create client err:%s\n", err)return}

defer conn.Close()

client :=jsonrpc.NewClient(conn)var reply interr= client.Call("Counter.Add", 10, &reply)

fmt.Printf("reply: %s, err: %s\n", reply, err)

}

上面的NewJsonRpcSocketServer()方法创建了一个基于tcp协议的json-rpc服务器,NewJsonRpcSocketClient()方法示范了golang端的简单调用(注意是基于tcp,而不是http协议!稍后会给出调用"github.com/gorilla/rpc/json"实现的基于http协议的调用方法)。但这不是重点,下面看一下Java客户端的调用,可以看出来,这也是一个基于socket的通信:

packagecn;importcom.googlecode.jsonrpc4j.JsonRpcClient;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;import java.net.*;/*** Created by geomantic on 15/8/21.*/

public classSocketClient {public static voidmain(String[] args) {try{

Socket socket= new Socket("127.0.0.1", 3333);

JsonRpcClient client= newJsonRpcClient();

InputStream ips=socket.getInputStream();

OutputStream ops=socket.getOutputStream();int reply = client.invokeAndReadResponse("Counter.Add", new Object[]{1001}, int.class, ops, ips);

System.out.println("reply: " +reply);

}catch(IOException e) {

e.printStackTrace();

}catch(Throwable throwable) {

throwable.printStackTrace();

}

}

}

上面的java代码初步示范了如何异步调用golang服务端的两个很重要的约束:

1.  golang服务端的方法名注册和调用保持一致,格式为: 结构体名.方法名, 如上面的Counter.Add。

2. 能够注册的方法必须满足指定的函数签名:

func (t *T) MethodName(argType T1, replyType *T2) error 。

入参有且只有两个,第一个是被调用函数的输入参数,第二个是被调用函数的输出参数。 返回值只有一个error类型。这三个参数一个都不能变。

但是基于tcp的调用,对于用惯了http协议的人会感觉写起来很蛋疼,可能更多的人还是习惯用http来解析。但是由于解决的方法有比较琐碎的细节处理,而且牵涉到一些第三方库的代码修改,考虑到篇幅问题准备另起一篇,在下一篇中示范一下用http协议通信实现的rpc实现。

 类似资料: