Thrift C++ 服务器和客户端开发实例--学习笔记
2017-04-13 18:39
537 查看
C++服务器和客户端开发
参考:thrift下C++服务器和客户端开发
参考:ThriftUsageC++
参考:Thrift 入门教程
Thrift环境搭建:
Ubuntu环境下Thrift的安装、编译以及测试
ubuntu下thrift的安装
RPC框架之Thrift分析
1 实现这个例子,我们大致要做以下几部分事情:
(1)书写.thrift文件
(2)生成cpp文件
(3)编写客户端
(4)编译cpp文件并执行
下面是详细的步骤:
(1)书写.thrift文件
学生信息是有结构的,所以我们使用thrift的struct即可,为了达到通信的目的,我们必须使用service。
所以最后书写成的student.thrift文件内容如下:
(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代码如下:
同时修改服务端的代码及文件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);
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
注意:
在自己的环境下要是把-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
3 运行结果:
先启动server.
再运行client.
server输出:
client执行结果:
参考:thrift下C++服务器和客户端开发
参考:ThriftUsageC++
参考:Thrift 入门教程
Thrift环境搭建:
Ubuntu环境下Thrift的安装、编译以及测试
ubuntu下thrift的安装
RPC框架之Thrift分析
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 4000 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
注意:
在自己的环境下要是把-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
相关文章推荐
- thrift C++服务器/客户端开发
- thrift下C++服务器和客户端开发
- thrift下C++服务器和客户端开发
- thrift下C++服务器和客户端开发
- ArcGIS客户端开发学习笔记(一)——AJAX机制
- IFS 客户端 开发学习笔记1
- Asp.net控件开发学习笔记(五)---Asp.net客户端状态管理
- Asp.net控件开发学习笔记-Asp.net客户端状态管理
- Sharepoint学习笔记---Sandbox Solution-- Full Trust Proxy--开发实例之(2、在Webpart中访问Full Trust Proxy)
- ArcGIS客户端开发学习笔记(二)——XML
- ATL开发指南学习笔记: COM与C++的VTable(虚拟表)
- C++/GDI+ 学习笔记(五)——应用实例——半透明的阴影效果
- Asp.Net Ajax 学习笔记23 利用Microsoft AJAX Library开发客户端组件(上)
- IFS 客户端 开发学习笔记3
- IFS 客户端 开发学习笔记5
- ArcGIS客户端开发学习笔记(五)——ArcGIS REST API基础
- 用c++开发sockets学习笔记
- gtk学习笔记1(安装c/c++和gtk开发环境)
- Asp.net控件开发学习笔记(九)----服务器控件事件
- 使用c++开发学习笔记