zoukankan      html  css  js  c++  java
  • 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
    ");
        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

  • 相关阅读:
    对公信贷系统与其他系统交互方式总结
    测试验收标准checklist
    测试风险汇报
    接口测试checklist
    52 | 深入浅出网站可扩展性架构设计
    51 | 深入浅出网站伸缩性架构设计
    html元素类型 块级元素、内联元素(又叫行内元素)和内联块级元素。(转载)
    IO流
    多线程
    Java网络编程
  • 原文地址:https://www.cnblogs.com/zhaoxd07/p/5387215.html
Copyright © 2011-2022 走看看