• Thrift安装及遇到问题并附带一个例子


    说明:

        可能是用windows时间长的关系,总感觉linux下的软件管理很麻烦。

        特意说明下:这里的方法非原创,都是在安装过程中遇到问题在搜索之后的整理。作为一种经验整理。

    ·安装:

      依赖库:

    基本:--应该是最小集,但我安装这些后还是缺少库。

      libboost-dev,libevent-dev,libtool,flex,bison,g++,automake,pkg-config,

      libboost-test-dev

      libmono-dev,ruby1.8-dev,libcommons-lang-java,php5-dev

    全部:

      debhelper(>=5),build-essential,mono-gmcs,python-dev,ant,

      libmono-dev,erlang-base,ruby1.8-dev,autoconf,python-support,

      automake,pkg-config,libtool,bison,flex,liboost-dev|libboost1.40-dev,

      python-all,python-all-dev,python-all-dbg,ruby,

      openjdk-6-jdk|java-sdk,libcommons-lang-java,

      libboost-test-dev|libboost-test1.40-dev,libevent-dev,

      perl(>=5.8.0-7),php5,php5-dev

    补充:

      我自己还看别的资料安装了appache ivy,不知道有没有影响。

      下载地址:

     一般都是自己上网搜索,去官网直接下载最好。不过还是附上地址:http://thrift.apache.org/

      步骤:

    0.在旧资料中的第一步是运行./bootstrap.sh的脚本,不过新版本(0.80)可略过;

    1.执行脚本:./configure --without-erlang –with-boost=/usr/include

                  (其中./configure也可以有其他的参数)

    2.sudo make(因为我是安装在/opt下的)

    3.sudo make install

    ·问题:

      关于boost安装:

    因为我原先学习使用boost了,所以我安装的全套的boost库。

      关于erlang问题:

    因为我在make的过程中总是在处理erlang过程出现问题,而我也没找到相关的解决方法,考虑到暂时先不用erlang,就关闭了erlang功能--使用参数without-erlang。

      uint32等类型不识别问题:

    深层的原因不知道,不过在TProtocol.h中有个#ifdef HAVE_NETINET_IN_H后跟#include <netinet/in.h>和#endif的语句块,这样的话默认不识别uint16_t等类型的。解决方法有两个:

      (推荐)在g++后加参数-DHAVE_NETINET_IN_H。

      (慎重)直接修改TProtocol.h等源代码。

    我采用的是第一种方法。

    网上其他资料:

      g++编译时加入下列宏定义即可。

      COMMON_DEF=-DHAVE_NETINET_IN_H -DHAVE_INTTYPES_H

      详细见:https://issues.apache.org/jira/browse/THRIFT-1326

      动态库链接问题:

    在编译正确后,运行程序时系统提示:error while loading shared libraries: libthrift0.8.0.so: cannot open shared object file: No such file or directory。。。的错误。解决方法有两个:

    (我采用)修改配置文件:在~/.bashrc里加上export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib:/usr/lib,之后用ldconfig命令是配置生效。

    原文:

      因为要使thrift,昨天和Makefile搏斗了一晚上,编译的时候加了-I$thrift_path,链接的时候加了-lthrift,好容易编译过了,结果运行的时候报了error while loading shared libraries: libthrift.so.0: cannot open shared object file: No such file or directory。。。
        解决方法:在~/.bashrc里加上export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/:/usr/lib/,总算搞定了。。还是找root在/etc/ld.so.conf里加一下?搞不清呀。。。
        thrift还是挺方便的。。。
    以下为zz:
    linux中与动态库连接的程序在运行时,需要将该动态库加载到内存中,linux根据LD_LIBRARY_PATH查找动态库,默认的动态库文件目录 为/usr/local/lib, /usr/lib。如果动态库没有位于默认目录中,或环境变量设置错误,都会引起错误,提示为:
           error while loading shared libraries: libxxx.xx: cannot open shared object file: No such file or directory

    解决办法:修改加对应的环境变量,然后再执行。

    export LD_LIBRARY_PATH=动态库所在目录:$LD_LIBRARY_PATH
    linux程序运行时加载共享库出现的错误:
    "error while loading shared libraries: xxxx: cannot open shared object file: No such file or directory"
    解决步骤:
    1、使用find命令查找缺失的xxxx共享库文件所在位置。参考:#find 目录 -name "xxxx*"
    2、将找到的目录位置写入 /etc/ld.so.conf 配置文件,这个文件记录了编译时使用的动态链接库的路径。
    3、然后使用ldconfig命令,使配置生效。
    注:使用 ldd 命令查看程序运行需要哪些库。 该命令用于判断某个可执行的 binary 档案含有什么动态函式库。该命令是一个shell脚本,不是程序。

      网上看到的问题但个人还没遇到:

      第二: undefined reference to `apache::thrift::TApplicationException::write(apache::thrift::protocol::TProtocol*) const'

             这也是存在的一个源码的bug,在protocol/TBinaryProtocol.h中,有两条语句

              static const int32_t

              这时,想到前面出现的问题,只要改成 static const uint32_t,问题就解决了

    3. 还有一点需要注意的就是,在一个编译命令中,遇到来一个非常奇怪的问题,一直没有找到合适的解决方法,后来发现把-lthrift放在给g++的最后就可以解决了,后来理解到原因可能是后面还有内容需要依赖于thrift库,而把他放在前面,后面对库的依赖就找不到来。。

       可以看出g++后面参数的顺序和位置对程序的编译和执行的影响还是挺大的。

    官方的使用教程和事例

    http://wiki.apache.org/thrift/ThriftUsageC%2B%2B

    ·例子:

    声明:原博客地址http://blog.csdn.net/hbuxiaoshe/article/details/6558391

    我用的是c++,所以我举一个c++的例子,简单说一下thrift的使用入门。

    例子描述是这样的:我们将学生信息(学号,姓名,性别,年龄)由客户端发送到服务端。

    实现这个例子,我们大致要做以下几部分事情:

    (1)书写.thrift文件

    (2)生成cpp文件

    (3)编写客户端

    (4)编译cpp文件并执行

    (1)书写.thrift文件

    学生信息是有结构的,所以我们使用thrift的struct即可,为了达到通信的目的,我们必须使用service。

    所以最后书写成的student.thrift文件内容如下:

    struct Student{
    1: i32 sno,
    2: string sname,
    3: bool ssex,
    4: i16 sage,
    }
    service Serv{
    void put(1: Student s),
    }

    (2)生成cpp文件

    生成cpp文件很简单,只需要一个thrift命令即可:

    /home/xiaoshe/opt/bin/thrift -r --gen cpp student.thrift

    --gen 后指定生成的语言,生成的cpp存储在目录gen-cpp下

    命令执行后,将会在./gen-cpp/目录下生成如下文件:

    Serv.cpp

    Serv.h

    Serv_server.skeleton.cpp

    student_constants.cpp

    student_constants.h

    student_types.cpp

    student_types.h

    注意文件的大小写:

    Serv开头的文件是由service生成的,这个关键字很重要,下面还会见到以它开头的类。

    student是根据student.thrift文件的名生成的。

    这些文件可以进行编译,生成最初的服务端。

    (3)编写客户端

    使用thrift命令后,我们并没有得到我们想要的客户端client源代码,因此客户端程序要由我们自己编写实现。然而很幸运,我们可以使用下面的代码段来编写我们client程序:

    [c-sharp] view plaincopy

    1. #include "Serv.h"  // 替换成你的.h
    2. #include <transport/TSocket.h>
    3. #include <transport/TBufferTransports.h>
    4. #include <protocol/TBinaryProtocol.h>
    5. using namespace apache::thrift;  
    6. using namespace apache::thrift::protocol;  
    7. using namespace apache::thrift::transport;  
    8. using boost::shared_ptr;  
    9. int main(int argc, char **argv) {  
    10.     boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));  
    11.     boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));  
    12.     boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));  
    13.     transport->open();  
    14. // 我们的代码写在这里
    15.     transport->close();  
    16. return 0;  

    保存成文件client.cpp

    (4)编译cpp文件并执行

    编译服务端:g++ -g -I/home/xiaoshe/opt/include/thrift -L/home/xiaoshe/opt/lib/ -lthrift Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -o server

    编译客户端:g++ -g -I/home/xiaoshe/opt/include/thrift -L/home/xiaoshe/opt/lib/ -lthrift -lm -pthread -lz -lrt -lssl Serv.cpp student_types.cpp student_constants.cpp client.cpp -o client

    运行服务端:./server

    运行客户端:./client

    (5)传输我们的数据Student信息

    到此客户端已经连上了服务端,但服务端只有这样的响应(No more data to read),因为二者之间还没有数据交互。

    我们把客户端当做发送端,修改client.cpp向服务端发送数据。

    在“// 我们的代码写在这里”

    写下我们的代码:

    // 先创建一个Student类型的变量,Student是我们在student.thrift中定义过的

    Student s;
    s.sno = 123;
    s.sname = "xiaoshe";
    s.ssex = 1;
    s.sage = 30;

    // 再定义一个对象client,又是以"Serv"开头的类

    ServClient client(protocol);

    // 最后调用put函数向服务端传输数据, put是student.thrift采用service定义的成员函数。

    // 调用put后,服务端也调用相应的put()
    client.put(s);

    服务端负责接收数据,也做相应修改:

    在类ServHandler()的put()中:

    printf("sno=%d sname=%s ssex=%d sage=%d/n", s.sno, s.sname.c_str(), s.ssex, s.sage);

    最后编译,运行服务端,启动客户端后,服务端收到消息,显示结果为:

    put
    sno=123 sname=xiaoshe ssex=1 sage=30

    至此,客户端已能向服务端发送数据了。

  • 相关阅读:
    文本特征选择的关键算法总结
    偏置-方差分解(Bias-Variance Decomposition)
    排列木桩
    七夕鹊桥分析
    第五十七课、模型视图设计模式(下)------------------狄泰软件学院
    第五十六课、模型视图设计模式(中)------------------狄泰软件学院
    第五十五课、模型视图设计模式(上)------------------狄泰软件学院
    第八十五课、多线程与界面组件的通信(下)------------------狄泰软件学院
    第八十四课、多线程与界面组件的通信(上)------------------狄泰软件学院
    第八十三课、另一种创建线程的方式------------------狄泰软件学院
  • 原文地址:https://www.cnblogs.com/davidyang2415/p/2421158.html
Copyright © 2020-2023  润新知