Thrift实际上是实现了C/S模式,通过代码生成工具将接口定义文件生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过thrift编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。它支持多种数据传输格式、数据传输方式和服务模型等,直接指定调用即可。感谢好文:原理介绍性:实际命令性:实际命令性:所以我的也算个实际命令性贴子了。0、准备篇因为要用C++,所以必须装Boost。其它语言的依赖看官方Wiki。下载Thrift: -> https://dist.apache.org/repos/dist/release/thrift/0.8.0/thrift-0.8.0.tar.gz下载Boost: ->1、安装Boostwgettar -xvzf boost_1_51_0.tar.gzcd boost_1_51_0/./bootstrap.sh最终输出:
Building Boost.Build engine with toolset gcc... tools/build/v2/engine/bin.linuxx86_64/b2
Detecting Python version... 2.6
Detecting Python root... /usr
Unicode/ICU support
for
Boost.Regex?... not found.
Generating Boost.Build configuration in project-config.jam...
Bootstrapping is done. To build, run:
./b2
To adjust configuration, edit
'project-config.jam'
.
Further information:
- Command line help:
./b2 --help
- Getting started guide:
http:
//www.boost.org/more/getting_started/unix-variants.html
- Boost.Build documentation:
http:
//www.boost.org/boost-build2/doc/html/index.html
./b2 install 搞完了报了一点小错,暂时没管,也证明没事。因为失败的占成功的比例太小了。...failed updating 58 targets......skipped 12 targets...Boost装到了/usr/local/include 和 /usr/local/lib里。因为这没加配置参数,这是默认结果。
2、安装Thrift
装Thrift之前的准备,依赖包提前装好:因为我准备按官方Wiki上搞C++的Server,Python的Client。所以:.
/configure
--with-cpp --with-boost=/usr/local
--with-python
--without-csharp --without-java --without-erlang --without-perl --without-php --without-php_extension --without-ruby --without-haskell --without-go
最终输出:thrift 0.8.0Building code generators ..... :Building C++ Library ......... : yesBuilding C (GLib) Library .... : noBuilding Java Library ........ : noBuilding C# Library .......... : noBuilding Python Library ...... : yesBuilding Ruby Library ........ : noBuilding Haskell Library ..... : noBuilding Perl Library ........ : noBuilding PHP Library ......... : noBuilding Erlang Library ...... : noBuilding Go Library .......... : noBuilding TZlibTransport ...... : yesBuilding TNonblockingServer .. : yesUsing Python ................. : /usr/bin/pythonIf something is missing that you think should be present,please skim the output of configure to find the missingcomponent. Details are present in config.log.makesudo make install3、试用例子我用的是Thrift的官方例子:thrift --gen cpp UserProfile.thriftthrift --gen py UserProfile.thrift生成的文件在gen-cpp gen-py两个目录中。我用C++ Server端和Python的客户端。C++ Server相关:UserStorage_server.skeleton.cpp注释掉或者去掉 using namespace ;(位置大概17行左右) 。这个是Server端的Main函数。Client的main函数文件要自己写。C++编译选项:编译服务端:g++ -g -I/usr/local/include/thrift/ -L/usr/local/lib -lthrift UserProfile_constants.cpp UserProfile_types.cpp UserStorage.cpp UserStorage_server.skeleton.cpp -o server -DHAVE_NETINET_IN_H
编译客户端:g++ -g -I/usr/local/include/thrift/ -L/usr/local/lib -lthrift -lm -pthread -lz -lrt -lssl UserProfile_constants.cpp UserProfile_types.cpp UserStorage.cpp client.cpp -o client -DHAVE_NETINET_IN_H然后直接运行./server即顺。程序运行时加载共享库出现的错误时如下解决:"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命令,使配置生效。我的是在/usr/local/lib/里。Python自己写的Client如下,运行即可:import sysimport pprintfrom urlparse import urlparsefrom thrift.transport import TTransportfrom thrift.transport import TSocketfrom thrift.transport import THttpClientfrom thrift.protocol import TBinaryProtocolimport UserStoragefrom ttypes import *up = UserProfile(uid=1, name="Test User", blurb="Thrift is great")# Talk to a server via TCP sockets, using a binary protocoltransport = TSocket.TSocket("localhost", 9090)transport.open()protocol = TBinaryProtocol.TBinaryProtocol(transport)# Use the service we already definedservice = UserStorage.Client(protocol)service.store(up)
运行Python出错,主要是加环境变量和改代码,这个贴子讲的挺好。我做了:export PYTHONPATH=/usr/lib/python2.6/site-packages4、Tutorial中的例子,另一个例子cd {THRIFTHOME}/thrift-0.8.0/tutorialthrift --gen cpp shared.thriftthrift --gen cpp tutorial.thrift搞完以后,gen-cpp中的Makefile要改一下:BOOST_DIR = /usr/local/include/boost/后面加-DHAVE_NETINET_IN_Hserver: CppServer.cpp g++ -o CppServer -I${THRIFT_DIR} -I${BOOST_DIR} -I../gen-cpp -L${LIB_DIR} -lthrift CppServer.cpp ${GEN_SRC} -DHAVE_NETINET_IN_Hclient: CppClient.cpp g++ -o CppClient -I${THRIFT_DIR} -I${BOOST_DIR} -I../gen-cpp -L${LIB_DIR} -lthrift CppClient.cpp ${GEN_SRC} -DHAVE_NETINET_IN_H
Server和Client都起来就行。Client输出如下:
cpp$ ./CppClientping()1+1=2InvalidOperation: Cannot divide by 015-10=5Check log: 5
杂记:
Client直接向Server发消息,那怎么从Server端拿回Response呢?这个例子已经显示了。Thrift中如此定义这个函数的:
i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch),Client中这样就可以把Server的返回值拿回来了。
int32_t quotient = client.calculate(1, work);