這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
這兩天因為工作需要查了一些跨語言的rpc介面。我這裡指的是包含序列化和tcp互動的。
主要查了一下以下三類:
1.ICE 這玩意不支援go,直接放棄。
2.GRPC,這玩意剛剛發布,還且全面使用C++11特性,我們生產環境目前還沒升級,他依賴於protobuf 3.0.0版本,這個還是beta版,拿過來編譯了下,依賴google的gmock。我的虛擬機器上連不上去,只能暫時作罷。
3.Thrift,這個從0.9.1 就開始完美(官方)支援go語言了,那就拿這個操刀吧。
註:C++測試環境ubuntu12.04LTS 核心 3.2.0-23 GCC版本4.6.3 Go就在win7筆記本上跑的。
第一件事安裝thrift,從官網下載最新thrift0.9.2版本。
編譯安裝參考 http://my.oschina.net/zc741520/blog/399049
libevent庫我這邊前段時間用到了就不用安裝了,使用的版本是2.0.22-stable
GO版本thrift從這個地址
git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift擷取哦
git.apache.org/thrift.git/lib/go/thrift永遠逾時。
thrift檔案如下:
namespace cpp hellowordnamespace go hellowordservice Test{string hello(1: string data);}
我把world寫錯了...=_=!
thrift --gen cpp helloword.thrift
thrift --gen go helloword.thrift
產生的C++檔案麼有問題,go裡面要修改下test.go和contants.go的thrift庫的位置
import("helloword""fmt""git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift""os""net")
下面開始擼C++代碼了。
C++ server端代碼
1 #include <thrift/concurrency/ThreadManager.h> 2 #include <thrift/concurrency/PosixThreadFactory.h> 3 #include <thrift/protocol/TBinaryProtocol.h> 4 #include <thrift/server/TSimpleServer.h> 5 #include <thrift/server/TThreadPoolServer.h> 6 #include <thrift/server/TThreadedServer.h> 7 #include <thrift/transport/THttpServer.h> 8 #include <thrift/transport/TServerSocket.h> 9 #include <thrift/concurrency/ThreadManager.h>10 #include <thrift/concurrency/PosixThreadFactory.h>11 #include <thrift/protocol/TBinaryProtocol.h>12 #include <thrift/server/TSimpleServer.h>13 #include <thrift/server/TThreadPoolServer.h>14 #include <thrift/server/TThreadedServer.h>15 #include <thrift/transport/THttpServer.h>16 #include <thrift/transport/TServerSocket.h>17 #include <thrift/transport/TTransportUtils.h>18 #include <thrift/TToString.h>19 #include <iostream>20 #include <string>21 #include "Test.h"22 #include <boost/bind.hpp>23 #include <boost/function.hpp>24 #include <thrift/protocol/TBinaryProtocol.h>25 #include <thrift/transport/TSocket.h>26 #include <thrift/transport/TTransportUtils.h>27 using namespace std;28 using namespace apache::thrift;29 using namespace apache::thrift::concurrency;30 using namespace apache::thrift::protocol;31 using namespace apache::thrift::transport;32 using namespace apache::thrift::server;33 using namespace ::apache::thrift;34 using namespace ::apache::thrift::protocol;35 using namespace ::apache::thrift::transport;36 using namespace ::boost;37 using namespace ::helloword;38 using ::boost::bind;39 40 class TestHandler : virtual public TestIf {41 public:42 TestHandler() { }43 44 void hello(std::string& _return, const std::string& data) {45 // if(data=="ping")46 printf("[%d] recv ping\n", (int)time(NULL));47 _return = "pong";48 printf("[%d] send pong\n", (int)time(NULL));49 }};50 51 int main(int argc, char **argv) {52 int port = 9000;53 shared_ptr<TestHandler> handler(new TestHandler());54 shared_ptr<TProcessor> processor(new TestProcessor(handler));55 shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));56 shared_ptr<TTransportFactory> transportFactory(new TTransportFactory());57 shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());58 TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);59 server.serve();60 return 0;61 }
C++ Client端代碼
1 #include <iostream> 2 #include <string> 3 #include <thrift/protocol/TBinaryProtocol.h> 4 #include <thrift/transport/TSocket.h> 5 #include <thrift/transport/TTransportUtils.h> 6 #include "Test.h" 7 using namespace std; 8 using namespace apache::thrift; 9 using namespace apache::thrift::protocol;10 using namespace apache::thrift::transport;11 using namespace helloword;12 int main(int argc,char ** argv) {13 string server = "127.0.0.1";14 if(argc>1)server= argv[1];15 boost::shared_ptr<TTransport> socket(new TSocket(server, 9000));16 boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));17 boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));18 TestClient client(protocol);19 try {20 transport->open();21 string cao="haha";22 client.hello(cao,cao);23 cout << "Hello"<< cao << endl;24 }25 catch(apache::thrift::TApplicationException &e)26 {27 cout<<e.what()<<endl;28 }29 return 0;30 }
編譯server端
g++ -o server server.cpp Test.cpp helloword_constants.cpp helloword_types.cpp -lthrift -lboost_system
編譯Client端
g++ -o client client.cpp Test.cpp helloword_constants.cpp helloword_types.cpp -lthrift -lboost_system
測試C++沒有問題。
寫GO的代碼:
GO server端
package mainimport("helloword""fmt""git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift""os")const (NetworkAddr = "192.168.20.76:9000")type Test struct{}func (this *Test) Hello(data string)(r string, err error){ //注意這裡,我的thrift代碼裡面寫的介面時小寫hello 在test.go裡面被fmt成大寫。fmt.Println("rec", data)r = data+"haha"fmt.Println("send", r)return}func main(){transportFactory := thrift.NewTTransportFactory() protocolFactory := thrift.NewTBinaryProtocolFactoryDefault() //protocolFactory := thrift.NewTCompactProtocolFactory() serverTransport, err := thrift.NewTServerSocket(NetworkAddr) if err != nil { fmt.Println("Error!", err) os.Exit(1) } handler := &Test{} processor := helloword.NewTestProcessor(handler) server := thrift.NewTSimpleServer4(processor, serverTransport, transportFactory, protocolFactory) fmt.Println("thrift server in", NetworkAddr) server.Serve()}
GO client代碼
package mainimport("helloword""fmt""git-wip-us.apache.org/repos/asf/thrift.git/lib/go/thrift""os""net")func main (){transportFactory := thrift.NewTTransportFactory()protocolFactory := thrift.NewTBinaryProtocolFactoryDefault()transport ,err := thrift.NewTSocket(net.JoinHostPort("127.0.0.1","9000"))if err != nil { fmt.Fprintln(os.Stderr, "error resolving address:", err) os.Exit(1) } useTransport := transportFactory.GetTransport(transport) client := helloword.NewTestClientFactory(useTransport, protocolFactory)if err := transport.Open(); err != nil { fmt.Fprintln(os.Stderr, "Error opening socket to server", " ", err) os.Exit(1) } defer transport.Close()for i := 0; i < 2; i++ { r1, e1 := client.Hello("hello") fmt.Println(i, "Call->", r1, e1) } }
當然測試也沒有問題。
下面就是交叉訪問了。
當然基於以上代碼同樣沒有問題,哈哈哈哈,因為問題被我K了啊 。附上。
C++ client端 與 GO server端
GO client VS C++ server 同樣沒有問題我就不了。
後面文章說下遇到的問題及分析。