Thrift框架使用C++的一個demo


Thrift編譯器會根據選擇的目標語言為server產生服務接口代碼,為client產生stubs,參數可以是基本類型和結構體。

代碼框架用的Thrift,為了了解結構,學習寫了一個thrift的Demo。雖然看起來很簡單,確實廢了不少功夫。下面列下我的步驟和我遇到的問題。

大家也可以參考這個博客:http://blog.csdn.net/hbuxiaoshe/article/details/6558391/

我這邊多出來的只有自己遇到的問題總結。

例子描述:我們將學生信息(學號,姓名,性別,年齡)由客戶端發送到服務端。

一 編寫thrift文件

學生信息使用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文件

thrift可以簡易生成不同語言的代碼,c++ python java等,此處我們只用--gen cpp第一個命令即可

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM