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

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

  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/davidyang2415/p/2421158.html
Copyright © 2011-2022 走看看