📜 ⬆️ ⬇️

Using Thrift in .NET

I want to share with you an example of how you can use such a handy thing as Thrift in your .NET projects.

For those who do not know, Thrift is a framework for facilitating the interaction between code written in different languages, namely C ++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C #, Cocoa, Smalltalk and OCaml.

Thrift is used and was originally created by Facebook. It was also repeatedly mentioned here on Habré, but I did not find examples for .NET, by the way, there is no step-by-step tutorial for .NET on the official site. In Google, to be honest, I also could not find it, although I could have looked badly.
Thrift allows you to once describe a service, data structures, and even exceptions, and then generate code for all supported languages. Thus, if you, for example, write a server using Thrift to .NET, then you
  1. Save a lot of time for writing client server application, for example using sockets.
  2. Almost automatically get customers in all supported languages.
In my example, I implement the simplest service that will simply return time. But having such a layout is easy enough to expand it to something useful.

So we need:
  1. Sources Thrift - we need them in order to build a library (class library) to connect to our project.
  2. Thrift compiler is a console utility that generates code in the required language from .thrift files.

Both can be taken from here.

Also at the end of the article I will give the source code of the working application, they already have a compiled library and compiler, you can take everything from there.

Step 1: Preparation
So after you have downloaded the sources, unpack them in any directory and go to
Open the solution and collect the project. After that you have the Thrift.dll library.

Step 2: Create our projects
Create 3 projects in Visual Studio and merge them into a solution.I did this:

Take the previously obtained Thrift.dll library and the downloaded Thrift compiler and put them in a directory in the solution.

Step 3: Generate code from the .thrift file
We describe our service and data structure. To do this, create a file TimeService.thrift with the following content:
namespace csharp TimeServer.Thrift

//Structure for returning Time
struct TimeInfoStruct{
1: string Time

service TimeService
TimeInfoStruct GetTime()

* This source code was highlighted with Source Code Highlighter .

and put it in the TimeServerCore project. Also add a reference to the Thrift.dll obtained in Step # 1 to the project.

Important: Do not save the .thrift file in Unicode encoding, my Thrift compiler did not want to generate anything from it, until I changed Unicode to another encoding in the studio in File-> Advanced Save Options.

This file contains almost the entire description of our client-server application.

You can manually call the Thrift compiler by pointing it to the .thrift file and get the necessary classes, but it is better to add a pre-build event to our project, in case we change TimeService.thrift

With my hierarchy of directories, I got this call
$(SolutionDir)\Thrift\thrift-0.5.0.exe -gen csharp -o $(ProjectDir) $(ProjectDir)\TimeService.thrift

"Thrift-0.5.0.exe" is the compiler itself, the option "-gen csharp" tells it that we need classes for C #, the option "-o $ (ProjectDir)" tells where to put the result, and the rest "$ (ProjectDir ) \ TimeService.thrift " indicates which file to compile.

So after the build (actually before, we have the pre-build event) TimeServerCore we will create 2 classes
TimeInfoStruct.cs is a structure for time transfer, in principle, the service method could simply return a string, but with a structure more interesting.
TimeService.cs is a service with our only method.

They also have code that is responsible for serialization / deserialization, visual ToString, and something else.

They will lie in the \ TimeServerCore \ gen-csharp \ TimeServer \ Thrift. The directory gen-csharp will always, apparently in order to scatter the code for different languages ​​in different folders, if more than one language is specified, and two directories down the hierarchy (\ TimeServer \ Thrift) are created because of the namespace specified in the .thrift file.

It is necessary to add these 2 files to the project, after that I did it like this:

Step 4: Server
We are engaged in the server. Add a reference to Thrift.dll in TimeServer, as well as to the TimeServerCore project in our solution. Then create a new class TimeServiceImplementation.cs .

In this class, we implement the methods of our service. In the generated TimeService.cs file, Thrift created a special interface for us that we should implement.

Here is the interface:
public class TimeService { //

public interface Iface {
TimeInfoStruct GetTime();

* This source code was highlighted with Source Code Highlighter .

as you can see there is only 1 function, which we described in the .thrift file.

Here is my implementation of this interface:
class TimeServiceImplementation : TimeService.Iface
public TimeInfoStruct GetTime()
return new TimeInfoStruct() { Time = DateTime .Now.ToString() };

* This source code was highlighted with Source Code Highlighter .

And so everything is almost ready, you need to force the server to start when the application starts and wait for clients:
static void Main( string [] args)
TimeServiceImplementation service = new TimeServiceImplementation();
TProcessor processor = new TimeService.Processor(service);
TServerTransport transport = new TServerSocket(1337, 1000);
TServer server = new TSimpleServer(processor, transport);


* This source code was highlighted with Source Code Highlighter .

We create our implementation of the server interface, after which we start the server on port 1337 and wait for connections. Here and all the code necessary to create the simplest server.
In addition to the TSimpleServer server implementation, the Thrift.dll library includes TThreadedServer and TThreadPoolServer.

Step 5: Customer

Client implementation is even easier:

static void Main( string [] args)
TTransport transport = new TSocket( "localhost" , 1337);
TProtocol proto = new TBinaryProtocol(transport);
TimeService.Client client = new TimeService.Client(proto);

TimeInfoStruct result = client.GetTime();

Console .WriteLine(result.ToString());
Console .ReadKey();

* This source code was highlighted with Source Code Highlighter .

Do not forget to add a reference to Thrift.dll and the project TimeServerCore to the client project.

After that, you can start the server first and then the client. Which should display the current time.

That's all. And most of the time we spent on the initial setup and familiarity with Thrift, and even then not so much. Now you can add new structures and methods to the service in our .thirft file, after which you can only write implementations of server methods.
Well, if you need clients or servers written in other languages, then classes for them can also be generated using Thrift.

For example, using Thrift a .NET client was obtained for the Cassandra database. Although creating Cassandra hardly Facebook planned to support .NET clients :)

Here are the promised sources:

Here is a link to the Thrift Wiki , although there is not a lot of information for .NET.

Source: https://habr.com/ru/post/106839/

All Articles