Open vieyahn2017 opened 5 years ago
例子来自333m
1.简介 Thrift是一个跨语言的服务部署框架,最初由Facebook于2007年开发,2008年进入Apache开源项目。Thrift通过一个中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java,Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk和OCaml),并由生成的代码负责RPC协议层和传输层的实现。类似的框架有googleprotocol,avro,message pack等。
2.架构
Thrift实际上是实现了C/S模式,通过代码生成工具将接口定义文件(*.thrift)生成服务器端和客户端代码(可以为不同语言),从而实现服务端和客户端跨语言的支持。用户在Thirft描述文件中声明自己的服务,这些服务经过编译后会生成相应语言的代码文件,然后用户实现服务(客户端调用服务,服务器端提服务)便可以了。其中protocol(协议层, 定义数据传输格式,可以为二进制或者XML等)和transport(传输层,定义数据传输方式,可以为TCP/IP传输,内存共享或者文件共享等)被用作运行时库。
3.支持的RPC与序列化格式与类型 数据类型
TCompactProtocol – 压缩格式
TJSONProtocol – JSON格式
TSimpleJSONProtocol –提供JSON只写协议, 生成的文件很容易通过脚本语言解析。
TDebugProtocol – 使用易懂的可读的文本格式,以便于debug12
3.12支持的数据传输方式 TFramedTransport – 以frame为单位进行传输,非阻塞式服务中使用。
TFileTransport – 以文件形式进行传输。
TMemoryTransport – 将内存用于I/O.java实现时内部实际使用了简单的ByteArrayOutputStream。
TZlibTransport – 使用zlib进行压缩, 与其他传输方式联合使用。当前无java实现。
3.13支持的服务模型
TSocket -阻塞式socker(一般用于客户端)
TSimpleServer – 简单的单线程服务模型,常用于测试
TThreadPoolServer – 多线程服务模型,使用标准的阻塞式IO。
TNonblockingServer – 单线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式)
TThreadedServer - 多线程服务模型,使用阻塞式IO,每个请求创建一个线程。 TThreadPoolServer – 线程池服务模型,使用标准的阻塞式IO,预先创建一组线程处理请求。 TNonblockingServer – 多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式)(C++服务)
THsHaServer - 多线程 non blocking的服务(java服务)
处理大量更新的话,主要是在TThreadedServer和TNonblockingServer中进行选择。TNonblockingServer能够使用少量线程处理大量并发连接,但是延迟较高;TThreadedServer的延迟较低。实际中,TThreadedServer的吞吐量可能会比TNonblockingServer高,但是TThreadedServer的CPU占用要比TNonblockingServer高很多。
3.2Thrift支持的类型 Thrift支持的类型系统包括预定义基本类型,用户自定义结构体,容器类型,异常和服务定义。
3.21基本类型 bool:布尔类型(true or value),占一个字节
byte:有符号字节
i16: 16位有符号整型
i32: 32位有符号整型
i64: 64位有符号整型
double:64位浮点数
string:未知编码或者二进制的字符串
*注意,thrift不支持无符号整型,因为很多目标语言不存在无符号整型(如java)。
还有枚举和常量。
3.22容器类型 Thrift容器与类型密切相关,它与当前流行编程语言提供的容器类型相对应,采用java泛型风格表示的。Thrift提供了3种容器类型:
List
Set
Map<t1,t2>:key/value对(key的类型是t1且key唯一,value类型是t2)。
容器中的元素类型可以是除了service以外的任何合法thrift类型(包括结构体和异常)。
3.23结构体、异常和服务 在面向对象语言中,thrift结构体被转换成类。它在语义上不同于结构体—当定义一个RPC服务时,开发者可能需要声明一个远程方法抛出一个异常。服务的定义方法在语法上等同于面向对象语言中定义接口。Thrift编译器会产生实现这些接口的client和server桩。
4.Thrift安装 Thrift涉及到网络和支持的多语言(可以选择性安装)。另外在支持Cpp语言时,可以使用boost库来作为Thrift作为它的底层库;支持java时要安装JDK和ant。另外还需要ssl服务。
4.1 openssl安装 因为thrift依赖于ssl服务所以先安装ssl.
官网下载ssl。
解压:tar xvf openssl-1.0.0g.tar.gz
配置编译动态库和支持64位 ./config -shared –fPIC
Make --》 make install
4.2 boost安装 参考程实blog:http://hi3ms.huawei.com/hi/group/4931/blog_149169.html
4.3 libevent安装 我安装的是1.4左右的稳定版本,主要是为了TNonblockingServer模式。
./configure ——》 make ——》 make install
4.4 安装Thrift
官网下载thrift。
解压:tar xvf 0.8
配置编译库./configure --with-boost=/usr/local LDFLAGS="-L/usr/local/ssl/lib" CPPFLAGS="-I/usr/local/ssl/include"
LDFLAGS找不到库的时候添加库路径 ,CPPFLAGS找不到头文件路径的时候添加头文件路径
出现:/usr/include/c++/4.3/cstdlib:124: error: '::malloc' has not been declared等错误的话:可以把config.h的 把#define malloc rpl_malloc注释掉(先重新configure ,再修改,再编译。。。)。
参考:http://hi.baidu.com/paopao_312/blog/item/9ed388ceda1f563eb700c86a.html
*注意make失败时,可能是头文件和库文件找不到,可以添加以下两个变量:
LD_LIBRARY_PATH:库文件
C_INCLUDE_PATH: (for C header files)
CPLUS_INCLUDE_PATH: (for C++ header files)
编写一个简单的demo,实现客户端与服务端的helloworld和结构体(类)传输,对于java也类似。
5.1定义*.thrift文件
namespace cpp demo //支持cpp,并定义空间;
namespace java demo //支持java;
//定义结构体,在支持面向对象的语言(如cpp、java)为类。
struct Student{
1:i32 sno,
2:string sname,
3:bool ssex,
4:i16 sage,
}
//定义方法
service Serv{
Student put(1: Student s),
string hello_word(1:string para)
}
5.2生成代码文件 生成cpp代码:
thrift -r --gen cpp student.thrift
如果是要生成java代码:
thrift -r --gen java student.thrift
其他语言类似。
生成的代码在./gen-cpp目录下
其中server端代码入口为:
Serv_server.skeleton.cpp
5.3编写客户端代码 //client.cpp
#include "Serv.h" // Your .h File
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using boost::shared_ptr;
using namespace demo;
void print_st(Student& s){
printf("num is: %d \n",s.sno);
printf("name is: %s \n",s.sname.c_str());
if(true ==s.ssex){
printf("sex is: man! \n");
}else{
printf("sex is: woman! \n");
}
printf("age is: %d \n",s.sage);
};
int main() {
boost::shared_ptr<TSocket> socket(newTSocket("localhost", 9090));
boost::shared_ptr<TTransport> transport(newTBufferedTransport(socket));
boost::shared_ptr<TProtocol> protocol(newTBinaryProtocol(transport));
ServClient client(protocol);
try{
transport->open();
//发送和接收stu对象并打印
Studentst;
st.__set_sno(222);
st.__set_sname("shuishuijiang");
Studentst_b;
print_st(st);
client.put(st_b,st);
print_st(st_b);
//helloworld!
std::string send = "hello server!";
std::string rec ;
client.hello_word(rec,send);
printf("Server say: %s\n", rec.c_str());
//关闭接口
transport->close();
}catch(TException &tx){
printf("ERROR: %s\n", tx.what());
}
return 1;
}
5.4修改服务端代码 //Serv_server.skeleton.cpp
// This autogenerated skeleton file illustrates howto build a server.
#include "Serv.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using boost::shared_ptr;
using namespace ::demo;
void print_st(const Student& s){
printf("num is: %d \n",s.sno);
printf("name is: %s \n",s.sname.c_str());
if(true ==s.ssex){
printf("sex is: man! \n");
}else{
printf("sex is: woman! \n");
}
printf("age is: %d \n",s.sage);
}
class ServHandler : virtual public ServIf{
public:
ServHandler() {
// Your initialization goes here
printf("Initializated!\n");
}
void put(Student& _return, const Student& s) {
// Your implementation goes here
printf("recived!\n");
print_st(s);
_return.__set_sname("shuishuihaoren");
_return.__set_ssex(true);
//add over!
printf("send!\n");
}
void hello_word(std::string& _return, const std::string& para) {
// Your implementation goes here
//要发送给的client的string;
_return = "Hi, client!";
//add over
printf("client say: %s\n",para.c_str());
}
};
int main(int argc, char **argv) {
int port =9090;
shared_ptr<ServHandler> handler(new ServHandler());
shared_ptr<TProcessor> processor(new ServProcessor(handler));
shared_ptr<TServerTransport> serverTransport(newTServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(newTBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory,protocolFactory);
server.serve();
return 0;
}
5.5编译、运行 用cmake来编译的:CMakeList.txt如下:
#CMake脚本的执行方法:1)cd build 2)cmake .. 3)make
#如果需要生成windows下的程序,第一步变为cmake -G,例如使用MinGW编译为:cmake -G “MinGW Makefiles”
cmake_minimum_required(VERSION 2.8)
PROJECT(demo_thrift)
#可执行文件生成在bin目录下
SET(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)
#库代码添加到此处
AUX_SOURCE_DIRECTORY(./gen-cpp/ DIR_SRCS)
#compileto lib
ADD_LIBRARY(demo_lib ${DIR_SRCS} )
#编译选项(Debug or Release)
SET(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb -lthriftnb -lthrift -lthriftnb -levent -lpthread")
SET(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall -lthriftnb -lthrift -lthriftnb -levent -lpthread")
#SET(CMAKE_BUILD_TYPE Release)
SET(CMAKE_BUILD_TYPE Debug)
#解决uint_32等类型编译不过的错误
SET(CMAKE_CXX_FLAGS "-DHAVE_NETINET_IN_H -DHAVE_INTTYPES_H")
SET(THRIFT_INCLUDE_PATH "/usr/local/include/thrift" )
SET(THRIFT_LIBRARY_PATH "/usr/local/lib" )
INCLUDE_DIRECTORIES(${THRIFT_INCLUDE_PATH})
LINK_DIRECTORIES(${THRIFT_LIBRARY_PATH})
#可执行代码添加到此处(main函数入口)
ADD_EXECUTABLE(client gen-cpp/client.cpp) #clent
TARGET_LINK_LIBRARIES( client demo_lib"thrift" )
ADD_EXECUTABLE(server gen-cpp/Serv_server.skeleton.cpp) #clent
TARGET_LINK_LIBRARIES( server demo_lib"thrift" )
创建外部编译目录:
mkdir build || rm -rf build/* && cd build && cmake .. && make all
运行服务端和客户端
./build/bin/server
./build/bin/client
kill服务端
pgrep -f server |xargs kill -9
文件目录
CMakeLists.txt gen-cpp student.thrift
gen-cpp文件夹:
Serv.cpp Serv.h Serv_server.skeleton.cpp student_constants.cpp student_constants.h student_types.cpp student_types.h
新建build文件夹后, 到build目录执行:
-- The C compiler identification is GNU 4.8.5
-- The CXX compiler identification is GNU 4.8.5
-- Check for working C compiler: /bin/cc
-- Check for working C compiler: /bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /bin/c++
-- Check for working CXX compiler: /bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /usr/local/thrift-0.10.0/yh/build
Scanning dependencies of target demo_lib
[ 20%] Building CXX object CMakeFiles/demo_lib.dir/gen-cpp/student_types.cpp.o
[ 40%] Building CXX object CMakeFiles/demo_lib.dir/gen-cpp/student_constants.cpp.o
[ 60%] Building CXX object CMakeFiles/demo_lib.dir/gen-cpp/Serv.cpp.o
[ 80%] Building CXX object CMakeFiles/demo_lib.dir/gen-cpp/Serv_server.skeleton.cpp.o
Linking CXX static library libdemo_lib.a
[ 80%] Built target demo_lib
Scanning dependencies of target server
[100%] Building CXX object CMakeFiles/server.dir/gen-cpp/Serv_server.skeleton.cpp.o
Linking CXX executable bin/server
/bin/ld: cannot find -lthriftnb
/bin/ld: cannot find -lthriftnb
/bin/ld: cannot find -levent
collect2: error: ld returned 1 exit status
make[2]: *** [bin/server] Error 1
make[1]: *** [CMakeFiles/server.dir/all] Error 2
make: *** [all] Error 2
搜了一个帖子说:
https://www.cnblogs.com/caosiyang/archive/2012/09/29/2708867.html
Thrift 服务端有如下模式:TSimpleServer TThreadpoolServer TThreadedServer TNonblockingServer
NonblockingServer是非阻塞的,编写非阻塞服务端程序需要链接库libthriftnb.a,即 -lthriftnb
如果找不到libthriftnb.a,可能是以下问题:
1.之前没有安装libevent,解决方法是安装libevent,再重新编译安装Thrift
2.安装libevent,没有生成libevent动态库
最初遇到这个问题是因为未安装libevent,但是安装libevent重新编译Thrfit仍然没有thriftnb静态库,
比较诧异,经过反复试验,发现如果没有libevent动态库,就不会生成thfirtnb静态库
由于编译安装第三方库时,习惯使用--disable-shared仅生成静态库,导致了问题的出现
另外,在编译安装libevent时,configure默认同时生成静态库和动态库
configure -h可以发现默认使用参数--enable-static --enable-shared
以上是以Apache Thrift v0.8.0和libevent-2.0.20-stable进行测试得出的结论
https://blog.csdn.net/qq_39436605/article/details/80893885 2018年07月03日 09:46:55 我是小超斌 阅读数:5369更多 个人分类: LINUX 在ubuntu上安装软件时,经常出现这样的问题:
/usr/bin/ld: cannot find -l****
例如:
/usr/bin/ld: cannot find -lgfortran 安装torch时出现
/usr/bin/ld: cannot find -lstdc++ 安装cuda时出现
这些问题都是因为找不到相应的lib文件,以上面的例子来说就是在系统中找不到libgfortran.so、libstdc++.so文件。
以libgfortran.so为例,我们先在系统中查找下该文件。命令为:
locate libgfortran
结果显示如下: 这里写图片描述
可以看到,有libgfortran.so.文件存在,但是没有libgfortran.so文件,因此我们进入/usr/lib/x86_64-linux-gnu/目录中,新建一个libgfortran.so的软连接,使其链接到已有的libgfortran.so文件(如libgfortran.so.3)。命令为:
sudo ln -s libgfortran.so.3 libgfortran.so
完成后查看下所有libgfortran.so文件ll libgfortran.so*
到此,该错误已经解决。
类似的/usr/bin/ld: cannot find -l****问题都可以通过这种方法解决。
2016年04月25日 11:10:41 runnerchen1 阅读数:4094 [root@localhost gen-cpp]# ./CppServer ./CppServer: error while loading shared libraries: libthrift-0.9.3.so: cannot open shared object file: No such file or directory [root@localhost gen-cpp]# ldd CppServer linux-vdso.so.1 => (0x00007ffcd4181000) libthrift-0.9.3.so => not found libstdc++.so.6 => /lib64/libstdc++.so.6 (0x00007f7a547ef000) libm.so.6 => /lib64/libm.so.6 (0x00007f7a544ed000) libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007f7a542d7000) libc.so.6 => /lib64/libc.so.6 (0x00007f7a53f15000) libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f7a53cf9000) /lib64/ld-linux-x86-64.so.2 (0x00007f7a54b21000)
临时解决方法:
export LD_LIBRARY_PATH=/usr/local/lib
不行
这样找文件也没有
find / -iname lthriftnb.so
不知道
是不是这样。
不测这个了。。。。。
后面用g++编译ok
g++ -g -Wall -I./ -I/usr/local/include/thrift Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -L/usr/local/lib/*.so -lthrift -o server
g++ -g -Wall -I./ -I/usr/local/include/thrift Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -L/usr/local/lib/*.so -lthrift -o server
不过也要导入环境变量,再运行
export LD_LIBRARY_PATH=/usr/local/lib
./server
现在的例子, server采用cmake编译不成功,client也不靠谱
因此,写了
import sys
import glob
sys.path.append('gen-py')
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol
from student.Serv import Client
from student.ttypes import Student
def print_st(stu):
print("num is: %s \n" % stu.sno)
print("name is: %s \n" % stu.sname)
if stu.ssex:
print("sex is: man! \n")
else:
print("sex is: woman! \n")
if stu.sage is None:
age = 18
print("age is: %s \n" % stu.sage)
def main():
transport=TSocket.TSocket('localhost', 9090)
transport=TTransport.TBufferedTransport(transport)
protocol=TBinaryProtocol.TBinaryProtocol(transport)
client=Client(protocol)
transport.open()
st = Student(222, "shuishuijiang", False, 16)
print_st(st)
st_b = client.put(st)
print_st(st_b)
send = "hello server!"
rec = client.hello_word(send)
print("Server say: %s\n", rec)
transport.close()
if __name__ == '__main__':
main()
启动服务端,执行本客户端,响应如下
num is: 222
name is: shuishuijiang
sex is: woman!
age is: 16
num is: 0
name is: shuishuihaoren
sex is: man!
age is: 0
('Server say: %s\n', u'Hi, client!')
表明是ok的
g++ 编译成功,是来自下面这个帖子的例子
2017年04月13日 18:39:33 Hao973 阅读数:9755 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/feng973/article/details/70160571
1 实现这个例子,我们大致要做以下几部分事情:
(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),
i32 icall(1: Student s),
string scall(1: Student s),
/*
string& srcall(1: Student s),
-----------------------------
-thrift -r --gen cpp student.thrift
-error:
- [ERROR:/root/test/thrift/student.thrift:12] (last token was '&')
- syntax error
- [FAILURE:/root/test/thrift/student.thrift:12] Parser error during include pass.
-----------------------------
*/
Student stcall(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代码如下:
#include "Serv.h"
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <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));
boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
transport->open();
//调用server服务
Student s;
s.sno = 123;
s.sname = "hao973";
s.ssex = 1;
s.sage = 30;
ServClient client(protocol);
printf("sno=%d sname=%s ssex=%d sage=%d\n", s.sno, s.sname.c_str(), s.ssex, s.sage);
//put
client.put(s);
//icall scall
std::string strname = "";
client.scall(strname, s);
printf("icall=%d, scall=%s\n", client.icall(s), strname.c_str());
//stcall
client.stcall(stu, s);
printf("student sno=%d sname=%s ssex=%d sage=%d\n", stu.sno, stu.sname.c_str(), stu.ssex, stu.sage);
transport->close();
return 0;
}
同时修改服务端的代码及文件Serv_server.skeleton.cpp中: 在Serv_server.skeleton.cpp文件中put函数中添加: //add by self printf(“sno=%d sname=%s ssex=%d sage=%d\n”, s.sno, s.sname.c_str(), s.ssex, s.sage);
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include "Serv.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using boost::shared_ptr;
class ServHandler : virtual public ServIf {
public:
ServHandler() {
// Your initialization goes here
}
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);
}
int32_t icall(const Student& s) {
// Your implementation goes here
printf("icall\n");
printf("sno=%d sname=%s ssex=%d sage=%d\n", s.sno, s.sname.c_str(), s.ssex, s.sage);
return s.sage;
}
void scall(std::string& _return, const Student& s) {
// Your implementation goes here
printf("scall\n");
printf("sno=%d sname=%s ssex=%d sage=%d\n", s.sno, s.sname.c_str(), s.ssex, s.sage);
_return = s.sname;
}
void stcall(Student& stu, const Student& s) {
// Your implementation goes here
printf("stcall\n");
printf("sno=%d sname=%s ssex=%d sage=%d\n", s.sno, s.sname.c_str(), s.ssex, s.sage);
stu.sno = s.sno + 1;
stu.sname = s.sname + "123";
stu.ssex = s.ssex;
stu.sage = s.sage + 10;
}
};
int main(int argc, char **argv) {
int port = 9090;
shared_ptr<ServHandler> handler(new ServHandler());
shared_ptr<TProcessor> processor(new ServProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
server.serve();
return 0;
}
2 编译链接:
编译程序命令: //服务器
g++ -g -Wall -I./ -I/usr/local/include/thrift Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -L/usr/local/lib/*.so -lthrift -o server
//客户端
g++ -g -Wall -I./ -I/usr/local/include/thrift Serv.cpp student_types.cpp student_constants.cpp Client.cpp -L/usr/local/lib/*.so -lthrift -o client
//服务器 g++ -g -Wall -I./ -I/usr/local/include/thrift Serv.cpp student_types.cpp student_constants.cpp Serv_server.skeleton.cpp -L/usr/local/lib/.so -lthrift -o server //客户端 g++ -g -Wall -I./ -I/usr/local/include/thrift Serv.cpp student_types.cpp student_constants.cpp Client.cpp -L/usr/local/lib/.so -lthrift -o client
注意: 在自己的环境下要是把-L/usr/local/lib/.so -lthrift 放在 .cpp 和 .o文件前面会出现链接错误。部分错误如下: /tmp/ccvtijvB.o:在函数‘ServClient::recv_put()’中: /root/test/thrift/gen-cpp/Serv.cpp:197:对‘apache::thrift::TApplicationException::read(apache::thrift::protocol::TProtocol)’未定义的引用 /tmp/ccvtijvB.o:在函数‘ServProcessor::dispatchCall(apache::thrift::protocol::TProtocol, apache::thrift::protocol::TProtocol*, std::__cxx11::basic_string
CC=g++ -g -Wall
CFLAGS = -I. -I/usr/local/include/thrift
LFLAGS = -L/usr/local/lib
LDEXEFLAGS = -lthrift
OBJS = Serv.o \
student_types.o \
student_constants.o
all:client server
Serv.o: Serv.cpp
$(CC) $(CFLAGS) -c $^ -o $@
student_types.o: student_types.cpp
$(CC) $(CFLAGS) -c $^ -o $@
student_constants.o: student_constants.cpp
$(CC) $(CFLAGS) -c $^ -o $@
Serv_server.skeleton.o: Serv_server.skeleton.cpp
$(CC) $(CFLAGS) -c $^ -o $@
Client.o: Client.cpp
$(CC) $(CFLAGS) -c $^ -o $@
server: $(OBJS) Serv_server.skeleton.o
$(CC) $(LFLAGS) $(OBJS) Serv_server.skeleton.o $(LDEXEFLAGS) -o $@
client: $(OBJS) Client.o
$(CC) $(LFLAGS) $(OBJS) Client.o $(LDEXEFLAGS) -o $@
clean:
rm -f ./*.o client server
3 运行结果: 先启动server. 再运行client.
server输出:
# ./server
put
sno=123 sname=hao973 ssex=1 sage=30
scall
sno=123 sname=hao973 ssex=1 sage=30
icall
sno=123 sname=hao973 ssex=1 sage=30
stcall
sno=123 sname=hao973 ssex=1 sage=30
client执行结果:
# ./client
sno=123 sname=hao973 ssex=1 sage=30
icall=30, scall=hao973
student sno=124 sname=hao973123 ssex=1 sage=40
cpp版本稍微复杂些 make比较麻烦