`
dengqsintyt
  • 浏览: 291275 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

thrift应用举例(c/c++作为服务端、java作为客户端)

 
阅读更多

最近做的一个项目,后端服务是c++写的,因所有参与这个项目的同事除了me之外,他们都不会c/c++语言。没有办法,我就承担了这个有意思的任务。下面通过实战例子,来剖析thrift的应用。

目录:

1.thrift是干什么用的?

      2.thrift语法?

      3.实战例子

            3.1 环境

            3.2 安装

            3.3 实战例子

      4.小结

 

     1.Thrift是干什么用的?

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

    2.Thrift语法

请参考网上其他文章。网上很多,不在赘述。重点了解:基本类型、容器、结构体、枚举、服务即可。

      2.1基本类型:

            bool: 布尔值 (true or false), one byte

            byte: 有符号字节

            i16: 16位有符号整型

            i32: 32位有符号整型

            i64: 64位有符号整型

            double: 64位浮点型

            string: Encoding agnostic text or binary string

            Note that: Thrift不支持无符号整型,因为Thrift目标语言没有无符号整型,无法转换

      2.2容器:

            Thrift容器与流行编程语言的容器类型相对应,采用Java泛型风格。它有3种可用容器类型:

                  list<t1>: 元素类型为t1的有序表,容许元素重复。

                  set<t1>:元素类型为t1的无序表,不容许元素重复。

                  map<t1,t2>: 键类型为t1,值类型为t2的kv对,键不容许重复。

      容器中元素类型可以是除了service外的任何合法Thrift类型(包括结构体和异常)。

      2.3 枚举和结构体

            枚举,和我们平常理解的枚举一样。

            这里只强调结构体就是类似于c/c++中的结构体(几乎一模一样)。类似于java中的实体bean。例子如下:

      枚举:

            enum TweetType {

                 TWEET,       // (1)

               RETWEET = 2, // (2)

                DM = 0xa,    // (3)

              REPLY

            }

 

  结构体:

            struct TxtClass{

                   1: string text,

                   2: string classId,

                   3: double score,

            }

      2.4 服务

      在流行的序列化/反序列化框架(如protocal buffer)中,Thrift是少有的提供多语言间RPC服务的框架。这是Thrift的一大特色。Thrift编译器会根据选择的目标语言为server产生服务接口代码,为client产生stubs。

这里就是thrift自动会生成的方法,我们的服务端也需要器生成的方法中进行编码。例子如下:

            service Twitter {

                      // A method definition looks like C code. It has a return type, arguments,

                      // and optionally a list of exceptions that it may throw. Note that argument

                      // lists and exception list are specified using the exact same syntax as

                      // field lists in structs.

                      void ping(),                                    // (1)

                      bool postTweet(1:Tweet tweet);                  // (2)

                      TweetSearchResult searchTweets(1:string query); // (3)

 

                      // The 'oneway' modifier indicates that the client only makes a request and

                      // does not wait for any response at all. Oneway methods MUST be void.

                      oneway void zip()                               // (4)

                }

 

<!--[if !supportLists]-->1.         3.<!--[endif]-->实战例子

      3.1 环境

            centOS6.4 64位操作系统

      3.2 安装

            首先,从官网http://thrift.apache.org/上下载thrift-0.8.0版本,你可以下载最新的版本。

            其次,从网上下载ant 和ivy。放在/usr目录下。

            Ant下载路径:http://ant.apache.org/

            Ivy下载路径:http://ant.apache.org/ivy/

      一切准备就绪,即可安装:

           3.2.1安装antivy(root用户)

第一步:安装 切复制ivy-2.2.0.jar到/usr/local/apache-ant-1.8.2/lib/目录中

       

# tar xzvf apache-ant-1.8.2-bin.tar.gz -C /usr/local 
# tar xzvf apache-ivy-2.2.0-bin-with-deps.tar.gz -C /usr/local
# cp  /usr/local/apache-ivy-2.2.0/ivy-2.2.0.jar  /usr/local/apache-ant-1.8.2/lib/
 

 

          第二步:编辑vim  /etc/ profile ,添加如下两行

        

export ANT_HOME=/usr/local/apache-ant-1.8.2 
PATH=$ANT_HOME/bin:$PATH
 

 

      第三步:解压thrift压缩文件。我用的是thrift-0.8.0.tar.gz

             

 tar  zxvf  thrift-0.8.0.tar.gz
 进入到thrift-0.8.0目录

 

   第四步:包的检查、安装(如果缺少包,请安装缺少的包)

       

./configure --prefix=/usr/local/ --with-boost=/usr/local --without-php
make
make install

 

   第五步:

   在终端输入:thrift –version  查看是否安装成功。

 

3.3 实战例子

特别注意:如下例子:演示的是thrift-0.7.0版本(因我服务器上安装的此版本)

    1.定义thrift文件:user.thrift     

struct User{
 1: string uid,
 2: string uname,
 3: bool usex,
 4: i16 uage,
}
service UserService{
 void add(1: User u),
 User get(1: string uid),
}
 

 

2.通过thrift的shell工具命令生成c++,java代码框架 

 

thrift -r --gen cpp user.thrift   
thrift -r --gen java user.thrift
   通过执行以上命令:会生成子目录gen-cpp,gen-java。
     3.通过执行如下命令,生成C/C++服务端代码
cp gen-cpp/UserService_server.skeleton.cpp UserServer.cpp
 
     4.修改服务端的代码,如下所示
     
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include <string>
#include <iostream> 
#include "UserService.h"  
#include <config.h>   
#include <protocol/TCompactProtocol.h>  
#include <server/TSimpleServer.h>  
#include <transport/TServerSocket.h>  
#include <transport/TBufferTransports.h>  
#include <concurrency/ThreadManager.h>  
#include <concurrency/PosixThreadFactory.h>  
#include <server/TThreadPoolServer.h>  
#include <server/TThreadedServer.h>  
  
using namespace ::apache::thrift;  
using namespace ::apache::thrift::protocol;  
using namespace ::apache::thrift::transport;  
using namespace ::apache::thrift::server;  
using namespace ::apache::thrift::concurrency;  
  
using boost::shared_ptr;
using namespace std; 

class UserServiceHandler : virtual public UserServiceIf {
 public:
  UserServiceHandler() {
    // Your initialization goes here
  }

  void add(const User& u) {
    // Your implementation goes here
    cout << "调用add方法" << endl;
  }

  void get(User& _return, const std::string& uid) {
    // Your implementation goes here
    _return.uid = "001";
    _return.uname = "dengqs";
    _return.usex = 1;
    _return.uage = 3;
    cout << "uid = " << _return.uid << endl;
    cout << "调用get方法" << endl;
  }

};

int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<UserServiceHandler> handler(new   UserServiceHandler());  
  shared_ptr<TProcessor> processor(new UserServiceProcessor(handler));  
  shared_ptr<TProtocolFactory> protocolFactory(new TCompactProtocolFactory());  
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());  
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(9090));  

  shared_ptr<ThreadManager> threadManager = ThreadManager::newSimpleThreadManager(10);  
  shared_ptr<PosixThreadFactory> threadFactory = shared_ptr<PosixThreadFactory>(new PosixThreadFactory());  
  threadManager->threadFactory(threadFactory);  
  threadManager->start();  
  printf("start user server...\n");  

  TThreadPoolServer server(processor, serverTransport,    transportFactory, protocolFactory, threadManager);  
  server.serve();  
  return 0;
}
 注意:我这里使用的是TCompactProtocol,则需要#include <config.h> ,还有就是Blocking的多线程服务器。
 
     5.书写Makefile文件,如下所示: 
BOOST_DIR = /usr/include/boost/
THRIFT_DIR = /usr/local/include/thrift
LIB_DIR = /usr/local/lib
GEN_SRC = ./gen-cpp/user_types.cpp ./gen-cpp/user_constants.cpp ./gen-cpp/UserService.cpp
default: server
server: UserServer.cpp
        g++ -g -o UserServer -I${THRIFT_DIR} -I${BOOST_DIR}  -I./gen-cpp -L${LIB_DIR} -lthrift UserServer.cpp ${GEN_SRC}
 注意:在当前目录下,执行:make命令。看是否有可执行文件UserServer生成。如果有,则编译成功。
 
     6.书写简单的运行脚本:run.sh文件,如下所示: 
nohup ./UserServer  >log  2>&1 &
   
       7.以上步骤,c++服务端操作完毕,执行如下命令开启服务:
./run.sh
或者
./UserServie
 
      8.写java client文件Demo.java
         注意需要引入thrift相关的jar。并且需要把第2步生成的gen-java目录下的文件拷贝到你的测试程序中。
         
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

import com.intyt.thrift.client.User;
import com.intyt.thrift.client.UserService;

public class Demo {
	
	public void start(){
		try {
			
			String ip = "10.x.x.x"; //服务端的ip
			int port = 9090;//端口
			
			TTransport socket = new TSocket(ip,port);
			TProtocol protocol = new TCompactProtocol(socket);
	        UserService.Client client = new UserService.Client(protocol);
	        socket.open();
	        
            User u = new User();  
            u.uid="003";  
            u.uname="dengqs_test";  
            u.usex=true;  
            u.uage=3;
            client.add(u);
            
            System.out.println(client.get(u.uid));  
            socket.close(); 
		}catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {  
            e.printStackTrace();  
        }
	}
	public static void main(String[] args) {
		Demo demo = new Demo();
		demo.start();
	}

}
 
以上步骤,可查看服务端和客户端时候有相关打印输出。如果有预期的打印输出,则测试成功。
祝你好运。
 
 
 
 

 

 

 

分享到:
评论
2 楼 dengqsintyt 2016-01-10  
不好意思,我好久不看博客了。刚看到你的问题。
这个报错看起来是源码中库的问题。我建议你换个版本试试。估计是版本的原因。
1 楼 影影禅 2015-09-08  
大神,请教下
./configure --prefix=/usr/local/ --with-boost=/usr/local --without-php 
make 
make install
我运行到make的时候会报错
src/thrift/transport/TSSLSocket.cpp:148: error: ‘TLSv1_1_method’ was not declared in this scope
src/thrift/transport/TSSLSocket.cpp:150: error: ‘TLSv1_2_method’ was not declared in this scope

相关推荐

    基于thrift开发的客户端和服务端

    通过Thrift,你可以用Java编写服务端,而用Python、C++或任何支持Thrift的其他语言编写客户端,实现无缝交互。Thrift还提供了许多优化功能,如多线程处理、异步调用和高级数据序列化选项,使得它成为构建分布式系统...

    Thrift java服务端、php客户端

    在Java服务端,开发者首先会定义一个Thrift IDL(接口定义语言)文件,这个文件中包含了服务的接口和数据结构。例如,可能有一个`Calculator`服务,包含加减乘除等操作。通过Thrift的编译器,这个IDL文件会被转换成...

    Thrift Java 服务器 客户端通信

    在Java环境中,Thrift提供了服务器和客户端的实现,使得Java应用能够方便地建立起高效的通信机制。下面我们将深入探讨Thrift在Java环境中的服务器和客户端通信过程。 首先,我们需要定义服务接口。这通常通过编写一...

    Thrift RPC客户端的服务化框架代码

    生成代码后,Thrift会为每种目标语言(如Java、Python、C++等)创建相应的客户端和服务器端代码。客户端代码提供了调用远程服务的接口,服务器端代码则包含了处理这些调用的实际逻辑。例如,对于Java,客户端代码会...

    Apache Thrift Java实战源码,包含了客户端和服务端源码

    在这个实战源码中,我们有两个主要的部分:`thrift-server` 和 `thrift-client`,分别代表服务端和客户端的实现。 服务端(thrift-server): 1. **Thrift IDL (接口定义语言)**:首先,你需要定义服务的接口和数据...

    用C#和C++写的Apache Thrift的小范例

    本例改编自Apache Thrift教程: http://mikecvet.wordpress.com/2010/05/13/apache-thrift-tutorial-the-sequel/ http://chanian.com/2010/05/13/thrift-tutorial-a-php-client/ 原教程使用的是c++ server和...

    Thrift之C++初体验

    thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, ...

    thrift java build jar

    本文将详细介绍如何使用 Thrift 在 Java 环境下构建 `.jar` 文件,以便在不同的 Java 应用中使用 Thrift 生成的服务。 1. **安装 Thrift** 首先,你需要在本地安装 Thrift 编译器。访问 Thrift 官方网站...

    Thrift下java服务器与客户端开发指南【精选文档】.doc

    Thrift下java服务器与客户端开发指南【精选文档】.doc

    C++(Qt)下的thrift的使用示例

    在C++环境中,Qt是一个非常流行的图形用户界面库,它为开发者提供了丰富的功能来构建跨平台的应用程序。而Thrift则是一种开源的软件框架,用于构建可伸缩的服务,它支持多种编程语言,包括C++,并且允许不同语言之间...

    Apache Thrift 使用说明

    Thrift 提供了一个集成的代码生成工具,允许开发者定义数据类型和服务接口,然后自动生成多种编程语言(如 C++ 和 Java)的客户端和服务器端代码,实现高效、可靠的远程过程调用(RPC)。 在 Ubuntu 系统下安装 ...

    ThriftDemo实现客户端服务端通讯.zip

    由于Thrift提供了跨语言的特性,这意味着服务端可以使用其他语言(如Java、Python)实现,客户端依然可以使用C#进行通信。 4. **VS2015-2019兼容性**:这个项目兼容Visual Studio 2015到2019版本,意味着它可以运行...

    qt 实现thrift的一个例子

    总结来说,这个例子展示了如何结合Qt的网络功能和Thrift的跨语言RPC机制来构建C++客户端和服务端应用。通过这种方式,开发者可以在不关心底层网络细节的情况下,专注于服务的业务逻辑,提高了开发效率和代码的可维护...

    c++,java跨语言通信

    本案例中,我们关注的是C++作为客户端与Java作为服务端的交互。这两种语言有着不同的特性和应用场景,但通过特定的技术和协议,可以实现它们之间的无缝通信。 1. **JNI(Java Native Interface)**:Java服务端可以...

    Thrift-java学习小结

    本文将基于Thrift的Java实现,总结学习过程中的一些关键知识点,旨在帮助理解Thrift的工作原理以及如何在Java环境中应用。 一、Thrift简介 Thrift是一种远程过程调用(RPC)框架,它通过定义一种中间描述文件(....

    编译后的thrift客户端

    编译后的thrift客户端,已经经过公司师父同意分享。 1. cp /Users/dxm/Desktop/thrift /usr/local/bin/ 2. echo $PATH 3. thrift 4. chmod +x /usr/local/bin/thrift 5. thrift 6. thrift -version

    python thrift搭建服务端和客户端测试程序

    Python Thrift 框架详解:构建服务端与客户端测试程序 Thrift 是一个高效的跨语言服务开发框架,由 Facebook 开发并贡献给了 Apache 基金会。它允许开发者定义数据类型和服务接口,然后自动生成多种编程语言的代码...

    Thrift下java服务器与客户端开发指南.pdf

    《Thrift下Java服务器与客户端开发指南》是指导开发者如何使用Thrift框架进行Java应用程序的服务器和客户端构建的文档。Thrift是一种开源的跨语言服务开发框架,它通过定义一个中间描述文件,可以生成多种编程语言的...

    thrift服务端和客户端实现Nifty.zip

    Nifty是facebook公司开源的,基于netty的thrift服务端和客户端实现。 然后使用此包就可以快速发布出基于netty的高效的服务端和客户端代码。 示例: public void startServer() { // Create the handler ...

    thrift_java_demo和安装包

    客户端则使用Thrift生成的Java客户端类,连接服务端,进行通信。 - 这个测试项目可能是为了演示如何使用Thrift进行RPC(Remote Procedure Call)调用,包括服务的定义、服务端的实现、客户端的调用流程等。 - 项目...

Global site tag (gtag.js) - Google Analytics