C++库(Thrift)

Thrift通信框架

0 简介

  Thrift是一个软件通讯框架,用来进行可扩展且跨语言的服务的开发,最初由Facebook于2007年开发,2008年进入Apache开源项目。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C, C++, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, C++Script, Node.js, Smalltalk, and OCaml 等等编程语言间无缝结合的、高效的服务。thrift允许你定义一个简单的定义文件中的数据类型和服务接口,作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的无缝跨编程语言。

1 Thrift的安装(Windows/C++)

  Thrift需要用到几个开源库:

  1) Boost (http://www.boost.org/)

  Boost库是一个经过千锤百炼、可移植、开源的C++库,作为C++标准库的后备,是C++标准化进程的发动机之一,是不折不扣的“准”标准库,大部分Boost库的使用只需要包含头文件即可,少数需要链接库。其中几个比较有名气的库为Regex正则表达式库、Thread可移植的C++多线程库、Pool内存池管理库、smart_ptr智能指针库等。

  2) Libevent (http://libevent.org/)

  Libevent是一个由C语言编写的、轻量级的开源高性能网络库,主要特点:事件驱动、高性能、轻量级、专注于网络、跨平台等。

  首先编译boost和libevent生成对应的lib文件,编译后文件自动存储位置为:

  .\boost_1_61_0\stage\     (windows下boost库的简单编译)

  .\libevent\libevent-2.0.21-stable\  (windows下编译及使用libevent)

  3) 下载、安装libthrift (https://thrift.apache.org)

  下载Thrift压缩包(v0.9.3),解压进入\thrift-0.9.3\lib\cpp,使用 VS2010及以上打开Thrift.sln,有libthrift,libthriftnb两个工程。libthriftnb工程是非阻塞(non-blocking)模式的服务器,非阻塞模式需要依赖libevent库。检查所需的include路径和lib路径,编译完成后在\thrift-0.9.1\lib\cpp\Debug(Release)中生成libthrift.lib和libthriftnb.lib。

2 Thrift基础

  (1)数据类型

  基本类型

    bool:布尔值,true 或 false,对应 C++ 的 bool

    byte:8 位有符号整数,对应 C++ 的 byte

    i16:16 位有符号整数,对应 C++ 的 short

    i32:32 位有符号整数,对应 C++ 的 int

    i64:64 位有符号整数,对应 C++ 的 long

    double:64 位浮点数,对应 C++ 的 double

    string:utf-8编码的字符串,对应 C++ 的 string

  结构体类型

    struct:定义公共的对象,类似于 C 语言中的结构体定义

  容器类型

    list:对应 C++ 的 list

    set:对应 C++ 的 set

    map:对应 C++ 的map

  异常类型

    exception:对应 C++ 的 Exception

  服务类型

    service:对应服务的类

  (2)通讯支持

   支持的数据传输协议(传输格式)

      TBinaryProtocol : 二进制格式.

      TCompactProtocol : 压缩格式

      TJSONProtocol : JSON格式

      TSimpleJSONProtocol : 提供JSON只写协议, 生成的文件很容易通过脚本语言解析

      tips: 客户端和服务端的协议要一致

  支持的数据传输方式

    TSocket -阻塞式socker

    TFramedTransport–以frame为单位进行传输,非阻塞式服务中使用。

    TFileTransport – 以文件形式进行传输。

    TMemoryTransport –将内存用于I/O. java实现时使用了简单的ByteArrayOutputStream。

    TZlibTransport – 使用zlib进行压缩, 与其他传输方式联合使用。当前无java实现。

  支持的服务模型

    TSimpleServer – 简单的单线程服务模型,常用于测试教学使用

    TThreadPoolServer – 多线程服务模型,使用标准的阻塞式IO。

    TNonblockingServer – 多线程服务模型,使用非阻塞式IO(需使用TFramedTransport数据传输方式)

3 一个例子

  (1)、编写idl文件

  编写calculate.idl如下:

1 namespace cpp calculate
2 service Calculator
3 {
4     i32 add(1:i32 add_num1, 2:i32 add_num2),
5     i32 subtract(1:i32 sub_num1, 2:i32 sub_num2)
6 }

  (2)、编译生成框架文件(C++)

  Thrift由两部分组成:编译器(在compiler目录下,采用C++编写)和服务器(在lib目录下),其中编译器的作用是将用户定义的thrift文件编译生成对应语言的代码,而服务器是事先已经实现好的、可供用户直接使用的RPC Server(当然,用户也很容易编写自己的server)。

  在idl文件所在路径打开cmd,输入:thrift-0.9.3.exe --gen cpp calculate.idl

  结果代码存放在gen-cpp目录下,其中的文件说明:

calculate_constants:idl文件中一些常量的定义

calculate_types:idl文件中定义的数据类型

Calculator:idl文件中定义的服务

  Calculator_server.skeleton:给出一个Server端代码框架

  (3)、编写服务端Server

将Calculator_server.skeleton.cpp内容拷贝,并在main函数开始部分添加代码:

  1  TWinsockSigleton::create(); //高版本不再需要
  2  int port = 9090;

  (4)、编写客户端Client

 1 #include "Calculator.h"
 2 #include <thrift/transport/TSocket.h>
 3 #include <thrift/transport/TBufferTransports.h>
 4 #include <thrift/protocol/TBinaryProtocol.h>
 5 #include <thrift/server/TSimpleServer.h>
 6 #include <thrift/transport/TServerSocket.h>
 7 #include <thrift/transport/TBufferTransports.h>
 8
 9 using namespace apache::thrift;
10 using namespace apache::thrift::protocol;
11 using namespace apache::thrift::transport;
12 using boost::shared_ptr;
13 using namespace  ::calculate;
14 int main(int argc, char **argv)
15 {
16     shared_ptr<TSocket> socket(new TSocket("127.0.0.1",9090));
17     shared_ptr<TTransport> transport(new TBufferedTransport(socket));
18     shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
19     CalculatorClient client(protocol);
20     try
21     {
22         transport->open();
23     }
24     catch(TTransportException)
25     {
26         transport->close();
27     }
28
29     int res_add = client.add(1, 2);
30     printf("client.add(%d, %d) = %d\n", 1, 2, res_add);
31     int res_subtract = client.subtract(3, 2);
32     printf("client.subtract(%d, %d) = %d\n", 3, 2, res_subtract);
33     transport->close();
34
35     getchar();
36     return 0;
37 }

  注:无论是Client还是Server,都必须包含必要的头文件和链接所需要的静态库文件。

  包含目录:工程配置页,C/C++ -> General -> Additional  Include Directories

  库目录:工程配置页,Linker -> General -> Additional  Library Directories,并在Input -> Additional Dependencies加入lib

  除此之外,还需要OpenSSL的包含路径和库路径,安装后指定即可。

  通过上面的例子分析可以看出,Thrift最重要的组件是编译器(采用C++编写),它为用户生成了网络通信相关的代码,从而大大减少了用户的编码工作。

  Thrift采用了C/S模型,不支持双向通信:client只能远程调用server端的RPC接口,但client端则没有RPC供server端调用,这意味着,client端能够主动与server端通信,但server端不能主动与client端通信而只能被动地对client端的请求作出应答。这种RPC模式在某些应用中存在缺陷,比如:有些应用,在大部分情况下,client端会主动向server端发请求或者向server端发送数据,而在少部分情况下,server端也需要主动向client发送一些命令,告知进行某些操作。为了解决该问题,通常使用双client/server,通信双方都既是client,也是server。该方案需要在通信双方之间建立两个通信通道,开启两个端口,这比较繁琐,且很不优雅。但仍是目前普遍采用的一套方案。

相关资料

  l  Apache Thrift 在Windows下的安装与开发

  l  董的博客Thirft框架介绍

  l  董的博客Thrift使用指南

  l  董的博客使用Thrift RPC编写程序

  l  董的博客浅谈Thrift内部实现原理

  l  Thrift: Scalable Cross-Language Services Implementation

  PS:

  CSDN提问:有没有人在windows下,用VS2010成功运行过thrift的程序?

  CSDN下载:解决在thrift0.9.3 cpp lib编译时候出现的问题

  需要例子源码的可给我留言~

时间: 2024-10-13 22:30:50

C++库(Thrift)的相关文章

Node 与 Thrift

背景:公司要用Node与其他语言(Java)写的服务通信. 1,服务端 helloServer.js var thrift = require('thrift'); var helloService = require('./HelloService'); var server = thrift.createServer(helloService, {     hello: function(para, success){         console.log("para: " + 

Thrift原理与使用实例

一 Thrift框架介绍 1 前言 Thrift是一个跨语言的服务部署框架,最初由Faceboo开发并进入Apache开源项目. Thrift特征如下: 1)Thrift有自己的跨机器通信框架,并提供一套库 2)Thrift是一个代码生成器,按照它的规则,可以生成多种编程语言的通信过程代码 Thrift通过中间语言(IDL, 接口定义语言)来定义RPC的接口和数据类型,然后通过一个编译器生成不同语言的代码(目前支持C++,Java, Python, PHP, Ruby, Erlang, Perl

window go thrift

代码在GitHub上托管 https://github.com/xej520/xingej-thrift/tree/master/hw-thrift 环境说明 windows 10 Intellij IDEA thrift-0.11.0.exe 服务端用java实现 客户端用go实现 用例的作用是,客户端将字符串传递给服务器,服务器将字符串转换成大写后,返回给客户端      创建maven工程(父模块) 删除自带的src目录(目前没用,删掉) 准备IDL文件 创建目录thrift 创建IDL文

go thrift oprot.Flush() not enough arguments in

代码在GitHub上托管 https://github.com/xej520/xingej-thrift/tree/master/hw-thrift 环境说明 windows 10 Intellij IDEA thrift-0.11.0.exe 服务端用java实现 客户端用go实现 用例的作用是,客户端将字符串传递给服务器,服务器将字符串转换成大写后,返回给客户端 ? ?? 创建maven工程(父模块) 删除自带的src目录(目前没用,删掉) ?? 准备IDL文件 创建目录thrift 创建I

thrift静态库问题

libthrift 要求boost库的智能指针,线程库以及librt libthriftnb 依赖libevent,因此需要链接libevent 从目前的情况下看,只能够编译出静态库版本的thrift,预示着整一个工程只能够链接静态库 Depending upon whether you are linking dynamically or statically and how your build environment it set up, you may need to include a

thrift 编译调用boost动态库

In the project properties you must also set HAVE_CONFIG_H as force include the config header: "windows/confg.h" By default lib/cpp/windows/force_inc.h defines: #define BOOST_ALL_NO_LIB 1 #define BOOST_THREAD_NO_LIB 1 This has for effect to have

linux安装thrift库

系统环境: [email protected] ~/t/gen-cpp> lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 14.04.3 LTS Release: 14.04 Codename: trusty [email protected] ~/t/gen-cpp> git:https://github.com/li-chunli/thrift_study thr

thrift c_glib 库序列化学习

thrift c_glib 库序列化学习 最近在项目中需要在不同的语言(c, c++, java, python) 之间传递消息, 模式是 server(C++)需要向订阅者(observer) 发送更新.大致的思路是server侦听某个端口, 然后observer 连接, 然后双方保持连接, 当有更新时, server 将消息下发给observer.由于需要跨语言,所以我们需要一个序列化的库, 项目中之前引入的thrift 正好可以解决, 在需要支持的各种语言中, c语言由于本身没有面向对象,

Openresty使用Thrift安装步骤

最新想用Golang与Openresty相互通讯调用,使用RPC协议来实现,后来研究最终选择了Thrift:主要还是FB实现了支持Lua和Go模块,直接编译就可以成功嵌套使用,非常方便:研究了两天最后编译成功,于是便把使用步骤做下记录. 1.Mac安装Thrift brew install thrift 2.Apache官网地址Thrift0.10下载地址 或者 git clone https://git-wip-us.apache.org/repos/asf/thrift.git thrift