Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / C++

Thrift: or How to RPC

0.00/5 (No votes)
14 Mar 2019CPOL2 min read 4.7K  
In search of a portable library, this time not for serialization, but for a portable RPC mechanism

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:

C++
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 basic usage:

thrift –gen cpp -out . service.thrift

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:

C++
#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:

C++
#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:

Thrift RPC server output:

Starting the server…
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, the complete source and build files are available at my GitHub.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)