Just like my previous Protocol Buffers post, this one is also meant as a brief introduction that will point you in the right direction rather than an exhaustive tutorial. Here we go…
Again we are in search of a portable library, this time not for serialization, but for a portable RPC mechanism. On Windows we have the WCF, but what if we want support for many platforms and programming languages? All that is answered by Thrift (also see here). Initially developed at Facebook it is now free and open source project.
Let’s start by creating a simple thrift file that defines a “service”, or a RPC server, with functions and parameters:
1 2 3 4 5 6 7 8 |
namespace cpp Service service Service { void ping(), void hello(1:string msg), oneway void async_call() } |
Here in a file service.thrift we have defined a RPC server called Service with three functions (one asynchronous) and a string parameter msg. Next we need to compile it. Just like protocol buffers, thrift is a code generator. It will produce everything needed to instantiate both the server and the client:
thrift –gen cpp -out . service.thrift
Thrift basic usage.
The above command will produce several header and source files for us. Now we are ready to implement our C++ client that will connect to the RPC server and issue remote procedure calls. The code is straight forward and easy to read and understand:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
#include <iostream> #include <thrift/transport/TSocket.h> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/transport/TTransportUtils.h> #include "Service.h" using namespace std; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace Service; int main(int argc, char** argv) { auto socket = make_shared<TSocket>("localhost", 9090); auto transport = make_shared<TBufferedTransport>(socket); auto protocol = make_shared<TBinaryProtocol>(transport); ServiceClient client(protocol); try { transport->open(); client.ping(); client.hello("Martin says hi!"); client.async_call(); transport->close(); } catch(TException& tx) { cout << "ERROR: " << tx.what() << endl; } return 1; } |
The server code is slightly more complicated, but not by much 🙂 In this post I’m using the most basic functions of thrift for illustration purposes. But know that it is quite capable of handling huge workloads and many connections. Here’s the corresponding server code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#include <iostream> #include <thrift/transport/TServerSocket.h> #include <thrift/protocol/TBinaryProtocol.h> #include <thrift/transport/TTransportUtils.h> #include <thrift/server/TSimpleServer.h> #include "Service.h" using namespace std; using namespace apache::thrift; using namespace apache::thrift::protocol; using namespace apache::thrift::transport; using namespace apache::thrift::server; using namespace Service; class ServiceHandler : public ServiceIf { public: ServiceHandler() = default; void ping() override { cout << "ping()" << endl; } void hello(const string& msg) override { cout << msg << endl; } void async_call() override { cout << "async_call()" << endl; } }; int main(int argc, char** argv) { TSimpleServer server( std::make_shared<ServiceProcessor>(std::make_shared<ServiceHandler>()), std::make_shared<TServerSocket>(9090), std::make_shared<TBufferedTransportFactory>(), std::make_shared<TBinaryProtocolFactory>()); cout << "Starting the server..." << endl; server.serve(); return 1; } |
The extra code here is the ServiceHandler class which will do the actual RPC work. Let’s put it all together now. After I start the server and execute the client program on my machine, I get the following output:
Starting the server…
Thrift RPC server output.
ping()
Martin says hi!
async_call()
It works! I hope you enjoyed this little introduction to thrift. Now go read all about it!
P.S. As always, complete source and build files available at my GitHub.
Hi Marcin,
Check http://Grpc.io out. You may it find interesting.
Thanks! I’ll check it out.