2021-05-12 14:32:11
Thrift編譯安裝指南
前言:thrift的版本問題比較麻煩,高版本的在c++上需要c++ 11的支援,而低版本則可能在go的支援上有問題,測試發現thrift 9.0以上需要c++ 11,而thrift 8.0則在go的支援上可能會存在問題。使用的發行版本是CentOS 6.5,GCC 4.4.7。最終選擇使用thrift-0.8.0來編譯安裝。
一. 編譯安裝
wget http://archive.apache.org/dist/thrift/0.8.0/thrift-0.8.0.tar.gz
tar -zxvf thrift-0.8.0.tar.gz
cd thrift-0.11.0
./configure #這一步設定可以選擇支援的語言,如Python,c++,go等。可以./configure --help來檢視可設定項。如./configure --without-go
make && make install
注意:在執行完configure後,會顯示實際上支援的庫,比如
thrift 0.11.0 Building C (GLib) Library .... : no Building C# (Mono) Library ... : no Building C++ Library ......... : yes Building D Library ........... : no Building Dart Library ........ : no Building dotnetcore Library .. : no Building Erlang Library ...... : no Building Go Library .......... : no Building Haskell Library ..... : no Building Haxe Library ........ : no Building Java Library ........ : no Building Lua Library ......... : no Building NodeJS Library ...... : no Building Perl Library ........ : no Building PHP Library ......... : no Building Plugin Support ...... : no Building Python Library ...... : yes Building Py3 Library ......... : yes Building Ruby Library ........ : no Building Rust Library ........ : no
如果編譯沒問題,那麼就可以檢視一下版本thrift -version
,如果能顯示,那麼就ok。
二. 測試使用
安裝完後要搞一個小程式測試一下。thrift的使用是從.thirft檔案開始的。
安裝完後,自帶的tutorial就有小例子,但感覺不夠直觀,來copy一個試試效果。
-
step 1 編寫thrift檔案 yang.thrift
struct Student{ 1: i32 sno, 2: string sname, 3: bool ssex, 4: i16 sage, } service Serv{ void put(1: Student s), i32 icall(1: Student s), string scall(1: Student s), /* string& srcall(1: Student s), ----------------------------- -thrift -r --gen cpp student.thrift -error: - [ERROR:/root/test/thrift/student.thrift:12] (last token was '&') - syntax error - [FAILURE:/root/test/thrift/student.thrift:12] Parser error during include pass. ----------------------------- */ Student stcall(1: Student s), }
-
step 2 生成原始碼
比如要生成c++程式碼,就可以
thrift -r --gen cpp yang.thrift
。這樣就能在目錄下生成一個gen-cpp目錄,裡面生成了多個檔案,其中的Serv_server.skeleton.cpp
就是伺服器端main函數入口檔案。--gen後指定生成的語言,yang.thrift就是編寫的thrift魔板。 -
step 3 編寫用戶端程式碼
step 2 生成了伺服器端的程式碼框架(也僅僅是個框架),但是用戶端的程式碼就要自己編寫了。
#include "Serv.h" //這裡包含的是伺服器端生成的標頭檔案,注意路徑 #include <transport/TSocket.h> #include <transport/TBufferTransports.h> #include <protocol/TBinaryProtocol.h> using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using boost::shared_ptr; int main(int argc, char **argv) { boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090)); boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); transport->open(); //呼叫server服務 Student s; s.sno = 123; s.sname = "hao973"; s.ssex = 1; s.sage = 30; ServClient client(protocol); printf("sno=%d sname=%s ssex=%d sage=%dn", s.sno, s.sname.c_str(), s.ssex, s.sage); //put client.put(s); //icall scall std::string strname = ""; client.scall(strname, s); printf("icall=%d, scall=%sn", client.icall(s), strname.c_str()); //stcall client.stcall(stu, s); printf("student sno=%d sname=%s ssex=%d sage=%dn", stu.sno, stu.sname.c_str(), stu.ssex, stu.sage); transport->close(); return 0; }
-
step 4 修改填充伺服器端的程式碼
這裡主要是填充服務的方法實現。在
Serv_server.skeleton.cpp
檔案put中新增printf(“sno=%d sname=%s ssex=%d sage=%dn”, s.sno, s.sname.c_str(), s.ssex, s.sage);
。其他幾個函數也是如此新增。下面是最後的結果。#include "Serv.h" #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/server/TSimpleServer.h> #include <thrift/transport/TServerSocket.h> #include <thrift/transport/TBufferTransports.h> using namespace ::apache::thrift; using namespace ::apache::thrift::protocol; using namespace ::apache::thrift::transport; using namespace ::apache::thrift::server; using boost::shared_ptr; class ServHandler : virtual public ServIf { public: ServHandler() { // Your initialization goes here } void put(const Student& s) { // Your implementation goes here printf("putn"); printf("sno=%d sname=%s ssex=%d sage=%dn", s.sno, s.sname.c_str(), s.ssex, s.sage); } int32_t icall(const Student& s) { // Your implementation goes here printf("icalln"); printf("sno=%d sname=%s ssex=%d sage=%dn", s.sno, s.sname.c_str(), s.ssex, s.sage); return s.sage; } void scall(std::string& _return, const Student& s) { // Your implementation goes here printf("scalln"); printf("sno=%d sname=%s ssex=%d sage=%dn", s.sno, s.sname.c_str(), s.ssex, s.sage); _return = s.sname; } void stcall(Student& stu, const Student& s) { // Your implementation goes here printf("stcalln"); printf("sno=%d sname=%s ssex=%d sage=%dn", s.sno, s.sname.c_str(), s.ssex, s.sage); stu.sno = s.sno + 1; stu.sname = s.sname + "123"; stu.ssex = s.ssex; stu.sage = s.sage + 10; } }; int main(int argc, char **argv) { int port = 9090; shared_ptr<ServHandler> handler(new ServHandler()); shared_ptr<TProcessor> processor(new ServProcessor(handler)); shared_ptr<TServerTransport> serverTransport(new TServerSocket(port)); shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory()); shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory()); TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); server.serve(); return 0; }
-
step 5 編譯連結
client 端:
g++ -DHAVE_NETINET_IN_H -g -Wall -I/usr/local/include/thrift -I/usr/include/boost -I./gen-cpp -I/usr/include Serv.cpp yang_constants.cpp yang_types.cpp client.cpp -L/usr/local/lib/ -lthrift -o client
這裡注意需要
-DHAVE_NETINET_IN_H
,否則會報一堆找不到定義。
然後是-I./gen-cpp
需要跟client.cpp中的標頭檔案相匹配。因為需要伺服器端生成的.h檔案
需要指定連結-lthrift庫,指定的是載/usr/local/lib
中,在執行時中可能會報找不到,需要在/etc/ld.so.conf.d/
中弄一個檔案,然後ldconfig,更新連結庫。
還有一個很坑的是:client.cpp需要伺服器端生成的cpp檔案,其中有類中方法的實現,所以編譯時需要指明。server端:
g++ -DHAVE_NETINET_IN_H -g -Wall -I/usr/local/include/thrift -I/usr/include/boost -I./ -I/usr/include Serv.cpp Serv_server.skeleton.cpp yang_constants.cpp yang_types.cpp -L/usr/local/lib/*.so -lthrift -o server
編譯完就可以執行,檢視效果了!done!
相關文章