Is it actually possible to do RPC calls from a server to a client with the net/rpc
package in Go? If no, is there a better solution out there?
Go中来自客户端和服务器的RPC
- 写回答
- 好问题 0 提建议
- 追加酬金
- 关注问题
- 邀请回答
-
3条回答 默认 最新
- dongluolie3487 2012-11-01 19:43关注
I am currently using thrift (thrift4go) for server->client and client->server RPC functionality. By default, thrift does only client->server calls just like net/rpc. As I also required server->client communication, I did some research and found bidi-thrift. Bidi-thrift explains how to connect a java server + java client to have bidirectional thrift communication.
What bidi-thrift does, and it's limitations.
A TCP connection has an incomming and outgoing communication line (RC and TX). The idea of bidi-thrift is to split RS and TX and provide these to a server(processor) and client(remote) on both client-application and server-application. I found this to be hard to do in Go. Also, this way there is no "response" possible (the response line is in use). Therefore, all methods in the service's must be "oneway void". (fire and forget, call gives no result).
The solution
I changed the idea of bidi-thrift and made the client open two connections to the server, A and B. The first connection(A) is used to perform client -> server communication (where client makes the calls, as usual). The second connection(B) is 'hijacked', and connected to a server(processor) on the client, while it is connected to a client(remote) on the server. I've got this working with a Go server and a Java client. It works very well. It's fast and reliable (just like normal thrift is).
Some sources.. The B connection (server->client) is set up like this:
Go server
// factories framedTransportFactory := thrift.NewTFramedTransportFactory(thrift.NewTTransportFactory()) protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() // create socket listener addr, err := net.ResolveTCPAddr("tcp", "127.0.0.1:9091") if err != nil { log.Print("Error resolving address: ", err.Error(), " ") return } serverTransport, err := thrift.NewTServerSocketAddr(addr) if err != nil { log.Print("Error creating server socket: ", err.Error(), " ") return } // Start the server to listen for connections log.Print("Starting the server for B communication (server->client) on ", addr, " ") err = serverTransport.Listen() if err != nil { log.Print("Error during B server: ", err.Error(), " ") return //err } // Accept new connections and handle those for { transport, err := serverTransport.Accept() if err != nil { return //err } if transport != nil { // Each transport is handled in a goroutine so the server is availiable again. go func() { useTransport := framedTransportFactory.GetTransport(transport) client := worldclient.NewWorldClientClientFactory(useTransport, protocolFactory) // Thats it! // Lets do something with the connction result, err := client.Hello() if err != nil { log.Printf("Errror when calling Hello on client: %s ", err) } // client.CallSomething() }() } }
Java client
// preparations for B connection TTransportFactory transportFactory = new TTransportFactory(); TProtocolFactory protocolFactory = new TBinaryProtocol.Factory(); YourServiceProcessor processor = new YourService.Processor<YourServiceProcessor>(new YourServiceProcessor(this)); /* Create thrift connection for B calls (server -> client) */ try { // create the transport final TTransport transport = new TSocket("127.0.0.1", 9091); // open the transport transport.open(); // add framing to the transport layer final TTransport framedTransport = new TFramedTransport(transportFactory.getTransport(transport)); // connect framed transports to protocols final TProtocol protocol = protocolFactory.getProtocol(framedTransport); // let the processor handle the requests in new Thread new Thread() { public void run() { try { while (processor.process(protocol, protocol)) {} } catch (TException e) { e.printStackTrace(); } catch (NullPointerException e) { e.printStackTrace(); } } }.start(); } catch(Exception e) { e.printStackTrace(); }
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报
悬赏问题
- ¥15 用土力学知识进行土坡稳定性分析与挡土墙设计
- ¥15 帮我写一个c++工程
- ¥30 Eclipse官网打不开,官网首页进不去,显示无法访问此页面,求解决方法
- ¥15 关于smbclient 库的使用
- ¥15 微信小程序协议怎么写
- ¥15 c语言怎么用printf(“\b \b”)与getch()实现黑框里写入与删除?
- ¥20 怎么用dlib库的算法识别小麦病虫害
- ¥15 华为ensp模拟器中S5700交换机在配置过程中老是反复重启
- ¥15 uniapp uview http 如何实现统一的请求异常信息提示?
- ¥15 有了解d3和topogram.js库的吗?有偿请教