Thrift編譯器會根據選擇的目標語言爲server產生服務接口代碼,爲client產生stubs,參數能夠是基本類型和結構體。java
代碼框架用的Thrift,爲了瞭解結構,學習寫了一個thrift的Demo。雖然看起來很簡單,確實廢了很多功夫。下面列下個人步驟和我遇到的問題。python
你們也能夠參考這個博客:http://blog.csdn.net/hbuxiaoshe/article/details/6558391/c++
我這邊多出來的只有本身遇到的問題總結。apache
例子描述:咱們將學生信息(學號,姓名,性別,年齡)由客戶端發送到服務端。框架
一 編寫thrift文件socket
學生信息使用thrift的struct便可,爲了達到通訊目的,咱們須要寫一個service。注意改出service的名字爲Serv,方法名字爲put。學習
因此最後寫成的student.thrift文件內容以下:測試
struct Student{ 1: i32 sno, 2: string sname, 3: bool ssex, 4: i16 sage, } service Serv{ void put(1: Student s), }
二 生成cpp文件spa
thrift能夠簡易生成不一樣語言的代碼,c++ python java等,此處咱們只用--gen cpp第一個命令便可.net
thrift -r --gen cpp student.thrift
#thrift -r --gen java student.thrift //生成java代碼
#thrift -r --gen py student.thrift //生成python代碼
以下生成7個文件:Serv開頭的文件是由service的名字生成的,查看Serv_server.skeleton.cpp能夠看到put方法。這些文件能夠編譯,生成最初的客戶端,編譯命令以下:
cd到gen-cpp所在的文件夾,執行以下編譯命令,注意生成的server可執行文件是在gen-cpp文件夾中的。
g++ -g -Ithrift -L Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -o server -lthrift
1 Serv.cpp 2 Serv.h 3 Serv_server.skeleton.cpp #簡單的server端代碼,能夠修改,通常都參照它來寫serve程序 4 student_constants.cpp 5 student_constants.h 6 student_types.cpp 7 student_types.h
三 編寫客戶端client.cpp
thrift最大的好處就是可用c++的服務端,java的客戶端;java的服務端,python的客戶端等。
中間"//咱們的代碼卸載這裏"後續能夠添加代碼進去進行測試。
注意此處,本來的include的.h文件路徑爲下路徑,我在運行時報錯了,因此換成了全路徑。
#include "Serv.h" // 替換成你的.h
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h> #include <protocol/TBinaryProtocol.h>
#include </home/xiaodan/MyThriftTest/student/gen-cpp/Serv.h>
#include </usr/local/include/thrift/transport/TSocket.h>
#include </usr/local/include/thrift/transport/TBufferTransports.h>
#include </usr/local/include/thrift/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)); //注意此處的ip和端口 boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket)); boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport)); transport->open(); // 咱們的代碼寫在這裏 transport->close(); return 0; }
四 編譯
我在這裏踩了好幾個坑,哭的都沒淚了。貼一下我成功的命令。
cd 進入gen-cpp編譯server端:g++ -g -Ithrift -L Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -o server -lthrift client.cpp我放在了gen-cpp的外面,因此編譯client端:
g++ -g -Ithrift -L -lm -pthread -lz -lrt -lssl gen-cpp/Serv.cpp gen-cpp/student_types.cpp gen-cpp/student_constants.cpp client.cpp -o client -lthrift
而後就能夠在對應目錄下分別看到兩個可執行文件
-rwxrwxr-x 1 xiaodan xiaodan 599962 Apr 13 13:59 client
-rwxrwxr-x 1 xiaodan xiaodan 663617 Apr 13 13:57 server
分別啓動,執行命令.
./server //能夠用ps -ef|grep server查看到啓動進程號
./client
五 發送消息進行通訊驗證
咱們把客戶端client.cpp當作發送端,編寫程序向服務端發送消息
在client.cpp中添加如下代碼
transport->open();
//********添加部分*********** Student s; s.sno = 123; s.sname = "xiaoshe"; s.ssex = 1; s.sage = 30; ServClient client(protocol); client.put(s);
//********添加部分***********
transport->close();
在Serv_server.skeleton.cpp中添加打印信息以下:
void put(const Student& s) { // Your implementation goes here printf("put\n"); printf("sno=%d sname=%s ssex=%d sage=%d/n", s.sno, s.sname.c_str(), s.ssex, s.sage); //********次行爲添加代碼******** }
再次編譯運行
1 啓動./server
2 再另外窗口執行./client
3 查看server窗口,便可看到打印信息以下:
put sno=123 sname=xiaoshe ssex=1 sage=30
七 問題與總結
1 編譯client.cpp提示"client.cpp:2:31: fatal error:transport/TSocket.h:No such file or directory"
在當前路徑下執行 find / -name 'TSocket' 發現該文件路徑爲/usr/local/include/thrift/transport/TSocket.h,因而更新client.cpp的include頭文件的路徑地址
2 編譯client.cpp提示"找不到Serv.h"
同1,更改Serv.h路徑爲全路徑便可
3 使用命令「g++ -g -Ithrift -L -lthrift -lm -pthread -lz -lrt -lssl gen-cpp/Serv.cpp gen-cpp/student_types.cpp gen-cpp/student_constants.cpp client.cpp -o client」編譯client.cpp,日誌報錯: undefined reference to `apache::thrift::TApplicationException::write(apache::thrift::protocol::TProtocol*) const'等等
解決:將編譯命令中的ithrift放到最後便可
好像是ithrift執行須要某些加載文件,放在前面的時候,它還沒加載會找不到。具體不記得了,在別人的博客裏看到過緣由,關了就沒再找到。感謝博客做者大神。
4 還有個問題,我沒解決。編譯完成執行事後,更新了Serv_server_skeletion.cpp和client.cpp,再次編譯時發生了錯誤,以下,求問怎麼回事?已經kill掉原server進程了。
/tmp/cckgAbGo.o: In function `ServProcessor::ServProcessor(boost::shared_ptr<ServIf>)': /home/xiaodan/MyThriftTest/student/gen-cpp/Serv.h:205: undefined reference to `vtable for ServProcessor' /home/xiaodan/MyThriftTest/student/gen-cpp/Serv.h:206: undefined reference to `ServProcessor::process_put(int, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, void*)' collect2: error: ld returned 1 exit status
5 server的啓動也可使用以下方式
Makefile文件: BOOST_DIR = /usr/include/boost/ THRIFT_DIR = /usr/local/include/thrift LIB_DIR = /usr/local/lib GEN_SRC = ./gen-cpp/user_types.cpp ./gen-cpp/user_constants.cpp ./gen-cpp/UserService.cpp default: server server: UserServer.cpp g++ -g -o UserServer -I${THRIFT_DIR} -I${BOOST_DIR} -I./gen-cpp -L${LIB_DIR} -lthrift UserServer.cpp ${GEN_SRC}
在路徑下執行make命令,便可看到日誌文件log