用thrift实现客户端和服务端的C++代码 - 金美光的小屋 - 博客频道 - CSDN.NET

删除回忆录丶 提交于 2020-01-23 21:33:42

用thrift实现客户端和服务端的C++代码 - 金美光的小屋 - 博客频道 - CSDN.NET

用thrift实现客户端和服务端的C++代码

分类: thrift 1058人阅读 评论(0) 收藏 举报

Getting started

The first thing you need to know is that the C++ code generated by Thrift compiles only on Unix based systems, although some success has been reported using Cygwin on Win32 in ThriftInstallationWin32.

Requirements

Make sure that your system meets the requirements as noted in ThriftRequirements

  • Thrift library files
  • Thrift header files.

Installing the Thrift library

Installing the Thrift library is trivial to link with the generated code.

1.    Download a snapshot of Thrift and extract if you haven't done so already - Direct Link

2.    Navigate to lib/cpp using the terminal of your choice

3.    Run  make to compile

4.    Run  make install to install the library. Your user needs root permissions.

Generating the server code

In this example we use an imaginary file called your_thrift_file.thrift:

#!/usr/local/bin/thrift --gen cpp

 

namespace cpp Test

/*

struct param    //thrift中的struct形式其实是参数,客户端要传递的参数类型必须在thrift文件中用struct先进行定义。注意只是客户端要传递的参数,服务器端的参数无需在thrift文件中定义。

{

  1:double left,

  2:double right,

}

/*

service Something { //service 中声明要实现的函数

  i32 ping()   //服务器端要实现的函数的声明

}

Now run:

thrift --gen cpp your_thrift_file.thrift

Exploring the generated code - The Server

The generated code should be under the gen-cpp directory. You will see a number of generated C++ and header files along with an automatically generated server skeleton code (in bold).

  • Something.cpp
  • Something.h
  • Something_server.skeleton.cpp
  • your_thrift_file_constants.cpp
  • your_thrift_file_constants.h
  • your_thrift_file_types.cpp
  • your_thrift_file_types.h

Implementing the Server

Copy the generated server skeleton to a file named Something_server.cpp and keep the original:

cp Something_server.skeleton.cpp Something_server.cpp

When this server is run in console it prints "ping" on the console window each time the function is called from a client.

Here's the autogenerated skeleton file to illustrate how to write a server: Something_server.cpp

#include "Something.h"

#include <protocol/TBinaryProtocol.h>

#include <server/TSimpleServer.h>

#include <transport/TServerSocket.h>

#include <transport/TTransportUtils.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 Test;

 

class SomethingHandler : virtual public SomethingIf {

 public:

  SomethingHandler() {

   // Your initialization goes here

  }

 

  int32_t ping() {

   // Your implementation goes here

printf("ping/n");

应该添加一条返回语句,源程序省略了,在此补上。

return 0;

  }

 

};

 

int main(int argc, char **argv) {

  int port = 9090; //端口是随机分配的 可修改,但要保持一致

  shared_ptr<SomethingHandler> handler(new SomethingHandler());

  shared_ptr<TProcessor> processor(new SomethingProcessor(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;

}

Compiling/Building the server

To quickly build a binary using a single command use:

mv Something_server.skeleton.cpp Something_client.cpp.backup

g++ -Wall -I/usr/local/include/thrift *.cpp -lthrift -o something 

//这里首先得把Something_server.skeleton.cpp的文件名做修改否则编译时会出现问题,我们不妨先把Something_server.skeleton.cpp文件名改成Something_client.cpp.backup,最后在把文件名改成cpp格式,并把clientcpp代码写在这里头

Compiling

You need to point your compiler to the thrift include path (CXX flag:  -I/usr/local/include/thrift)

g++ -Wall -I/usr/local/include/thrift -c Something.cpp -o something.o

g++ -Wall -I/usr/local/include/thrift -c Something_server.cpp -o server.o

g++ -Wall -I/usr/local/include/thrift -c your_thrift_file_constants.cpp -o constants.o

g++ -Wall -I/usr/local/include/thrift -c your_thrift_file_types.cpp -o types.o

Linking

You need to point your linker to the thrift library. (Linker flag:  -lthrift  or  -l/usr/local/lib/libthrift.so 

g++ -L/usr/local/lib -lthrift *.o -o Something_server

Writing the client code

thrift generates a client interface, but you have to hook it up a bit on your own.

以下的代码是标准的客户端代码模板,把这段代码copyclientcpp文件中,黄色标记的部分是主要需要修改的地方。

#include "Something.h"  // As an example

 

#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 namespace Test;

 

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));

 

  SomethingClient client(protocol);

  transport->open();

client.ping();/*客户端只要写了这条语句,服务器就将执行。

                 其他的语句都是套话。可以直接copy

              ping是执行的函数名,在thrift中声明了。

如果函数的原型,既ping是一个带参数的函数,则使用ping函数之前先进行参数的赋值等操作,如

  param op; 这个param结构体也需要在thrift文件中先定义。

  op.left = 2.0;

  op.right = 3.5;

client.ping(op);*/

  transport->close();

 

  return 0;

}

Compiling

再次把Something_client.cpp.backup改成Something_client.cpp

mv Something_client.cpp.backup Something_client.cpp

g++ -Wall -I/usr/local/include/thrift -c Something_client.cpp -o client.o

Linking

g++ -L/usr/local/lib -lthrift client.o something.o constants.o types.o -o Something_client

也可以把所有的语句做成一个makefile,如下

Compiling/Building everything with Makefile

GEN_SRC := Something.cpp your_thrift_file_constants.cpp your_thrift_file_types.cpp

GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))

 

THRIFT_DIR := /usr/local/include/thrift

BOOST_DIR := /usr/local/include

 

INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)

 

.PHONY: all clean

 

all: something_server something_client

 

%.o: %.cpp

        $(CXX) -Wall $(INC) -c $Slt; -o $@

 

something_server: Something_server.o $(GEN_OBJ)

        $(CXX) -L/usr/local/lib -lthrift $^ -o $@

 

something_client: Something_client.o $(GEN_OBJ)

        $(CXX) -L/usr/local/lib -lthrift $^ -o $@

 

clean:

        $(RM) *.o something_server something_client

Appendix: About TNonblockingServer

If you are writing an application that will serve a lot of connection (like php front end calling thrift service), you'd better use TNonblockingServer. TNonblockingServer can accept a lot of connections while throttling the processor threads using a pool.

* TNonblockingServer with a thread pool is the c++ alternative of the JAVA THsHaServer; * TNonblockingServer withOUT a thread pool is the c++ alternative of the JAVA TNonblockingServer;

Server code with thread pool:

    shared_ptr<TProcessor> processor(new SomethingProcessor(handler));

    shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());

 

    // using thread pool with maximum 15 threads to handle incoming requests

    shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(15);

    shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());

    threadManager->threadFactory(threadFactory);

    threadManager->start();

    TNonblockingServer server(processor, protocolFactory, 8888, threadManager);

    server.serve();

 

    // ...

C++ client code (you have to use TFramedTransport here):

    boost::shared_ptr<TSocket> socket(new TSocket("localhost", 8888));

    boost::shared_ptr<TTransport> transport(new TFramedTransport(socket));

    boost::shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));

 

    SomethingClient client(protocol);

    transport->open();

    // do something here...

    transport->close();

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!