`
jinghong
  • 浏览: 55506 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用thrift做c++,java和python的相互调用

阅读更多
linux上安装thrift见
http://jinghong.iteye.com/blog/1102535
thrift做为跨语言调用的方案有高效,支持语言较多,成熟等优点;代码侵入较强是其弱点。
下面记录以C++做服务器,C++,java和python做客户端的示例,这个和本人现在工作环境吻合,使用多线程长连接的socket来建立高效分布式系统的跨语言调用平台。
遗憾的是目前版本(0.7.0)的C语言还不支持Compact协议,导致在现在的环境中nginx c module调用thrift要使用binary协议。thrift开发团队似乎对C语言不太感冒。
1.定义idl文件acsuser.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.生成c++,java和python代码框架
thrift -r --gen cpp acsuser.thrift 
thrift -r --gen java acsuser.thrift 
thrift -r --gen py acsuser.thrift 

这时生成子目录gen-cpp,gen-java,gen-py

3.生成C++服务端代码
cp gen-cpp/UserService_server.skeleton.cpp UserServer.cpp

修改UserServer.cpp
#include "UserService.h"
#include <config.h>
//#include <protocol/TBinaryProtocol.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;

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

  void add(const User& u) {
    // Your implementation goes here
    printf("uid=%s uname=%s usex=%d uage=%d\n", u.uid.c_str(), u.uname.c_str(), u.usex, u.uage);
  }

  void get(User& _return, const std::string& uid) {
    // Your implementation goes here
    _return.uid = "leo1";
    _return.uname = "yueyue";
    _return.usex = 1;
    _return.uage = 3;
    printf("uid=%s uname=%s usex=%d uage=%d\n", _return.uid.c_str(), _return.uname.c_str(), _return.usex, _return.uage);
  }

};

int main(int argc, char **argv) {
  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的多线程服务器

4.生成C++的client文件UserClient.cpp
#include "UserService.h"
#include <config.h>
#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TCompactProtocol.h>

using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;

using boost::shared_ptr;

int main(int argc, char **argv) {
        boost::shared_ptr<TSocket> socket(new TSocket("localhost", 9090));
        boost::shared_ptr<TTransport> transport(new TBufferedTransport(socket));
        boost::shared_ptr<TProtocol> protocol(new TCompactProtocol(transport));

        transport->open();

        User u;
        u.uid = "leo";
        u.uname = "yueyue";
        u.usex = 1;
        u.uage = 3;

        UserServiceClient client(protocol);
        client.add(u);

        User u1;
        client.get(u1,"lll");

        transport->close();
        printf("uid=%s uname=%s usex=%d uage=%d\n", u1.uid.c_str(), u1.uname.c_str(), u1.usex, u1.uage);
        return 0;
}


5.生成Makefile
BOOST_DIR = /usr/local/include/boost/
THRIFT_DIR = /usr/local/include/thrift
LIB_DIR = /usr/local/lib
GEN_SRC = ./gen-cpp/acsuser_types.cpp ./gen-cpp/acsuser_constants.cpp ./gen-cpp/UserService.cpp
default: server client
server: UserServer.cpp
        g++ -g -o UserServer -I${THRIFT_DIR} -I${BOOST_DIR}  -I./gen-cpp -L${LIB_DIR} -lthrift UserServer.cpp ${GEN_SRC}
client: UserClient.cpp
        g++ -g -o UserClient -lm -pthread -lz -lrt -lssl -I${THRIFT_DIR} -I${BOOST_DIR}  -I./gen-cpp -L${LIB_DIR} -lthrift UserClient.cpp ${GEN_SRC}
clean:
        $(RM) -r UserServer UserClient


6.启动c++ server
./UserServer

7.测试c++ client
./UserClient

8.写java client文件UserClient.java
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TFramedTransport;
import org.apache.thrift.transport.TNonblockingSocket;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TTransportException;

//import UserService.Client;

public class UserClient {
    private void start() {
        try {
            TTransport socket = new TSocket("localhost", 9090);
            //TTransport transport = new TFramedTransport(socket);
            TProtocol protocol = new TCompactProtocol(socket);

            UserService.Client client = new UserService.Client(protocol);
            socket.open();
            System.out.println(client.get("lll"));

            User u = new User();
            u.uid="leojava";
            u.uname="yueyue";
            u.usex=true;
            u.uage=3;
            client.add(u);
            socket.close();

        } catch (TTransportException e) {
            e.printStackTrace();
        } catch (TException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        UserClient c = new UserClient();
        c.start();

    }
}

编译和运行java client
javac -classpath /usr/local/lib/libthrift-0.7.0.jar:/usr/local/lib/log4j-1.2.14.jar:/usr/local/lib/commons-logging-1.1.1.jar:/usr/local/lib/slf4j-api-1.5.8.jar UserClient.java ./gen-java/*.java
java -classpath .:./gen-java:/usr/local/lib/libthrift-0.7.0.jar:/usr/local/lib/log4j-1.2.14.jar:/usr/local/lib/commons-logging-1.1.1.jar:/usr/local/lib/slf4j-api-1.5.8.jar:/usr/local/lib/slf4j-log4j12-1.5.8.jar UserClient

9.写Python client文件PythonClient.py
#!/usr/bin/env python
import sys
sys.path.append('./gen-py')
from acsuser import UserService
from acsuser.ttypes import *
from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TCompactProtocol

# Make socket
transport = TSocket.TSocket('localhost', 9090)
# Buffering is critical. Raw sockets are very slow
transport = TTransport.TBufferedTransport(transport)
# Wrap in a protocol
protocol = TCompactProtocol.TCompactProtocol(transport)
# Create a client to use the protocol encoder
client = UserService.Client(protocol)
# Connect!
transport.open()
# Call Server services  
u = client.get('lll')
print 'uid=%s uname=%s usex=%d u.uage=%d' %(u.uid,u.uname,u.usex,u.uage)

u1 = User()
u1.uid='leo'
u1.uname='yueyue'
u1.usex=1
u1.uage=3
client.add(u1)

执行python client代码
chmod 777 PythonClient.py
./PythonClient.py

分享到:
评论
3 楼 conansadan 2012-11-15  
要用GCC来编译,如果用APPLE LLVM是link不上的。
2 楼 visoeclipse 2012-05-07  
Undefined symbols for architecture x86_64:
  "vtable for apache::thrift::server::TThreadPoolServer", referenced from:
      apache::thrift::server::TThreadPoolServer::TThreadPoolServer<apache::thrift::TProcessor>(boost::shared_ptr<apache::thrift::TProcessor> const&, boost::shared_ptr<apache::thrift::transport::TServerTransport> const&, boost::shared_ptr<apache::thrift::transport::TTransportFactory> const&, boost::shared_ptr<apache::thrift::protocol::TProtocolFactory> const&, boost::shared_ptr<apache::thrift::concurrency::ThreadManager> const&, boost::enable_if<boost::is_convertible<apache::thrift::TProcessor*, apache::thrift::TProcessor*>::type, void*>::type)in UserServer.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "vtable for apache::thrift::transport::TBufferedTransport", referenced from:
      apache::thrift::transport::TBufferedTransport::TBufferedTransport(boost::shared_ptr<apache::thrift::transport::TTransport>)in UserServer.o
  NOTE: a missing vtable usually means the first non-inline virtual member function has no definition.
  "apache::thrift::transport::TServerSocket::TServerSocket(int)", referenced from:
      _main in UserServer.o
  "apache::thrift::concurrency::ThreadManager::newSimpleThreadManager(unsigned long, unsigned long)", referenced from:
      _main in UserServer.o
  "apache::thrift::concurrency::PosixThreadFactory::PosixThreadFactory(apache::thrift::concurrency::PosixThreadFactory::POLICY, apache::thrift::concurrency::PosixThreadFactory::PRIORITY, int, bool)", referenced from:
      _main in UserServer.o
  "apache::thrift::server::TThreadPoolServer::serve()", referenced from:
      _main in UserServer.o
  "apache::thrift::server::TThreadPoolServer::~TThreadPoolServer()", referenced from:
      _main in UserServer.o
  "apache::thrift::TApplicationException::write(apache::thrift::protocol::TProtocol*) const", referenced from:
      UserServiceProcessor::process(boost::shared_ptr<apache::thrift::protocol::TProtocol>, boost::shared_ptr<apache::thrift::protocol::TProtocol>, void*)in UserService.o
      UserServiceProcessor::process_fn(apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, int, void*)in UserService.o
      UserServiceProcessor::process_add(int, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, void*)in UserService.o
      UserServiceProcessor::process_get(int, apache::thrift::protocol::TProtocol*, apache::thrift::protocol::TProtocol*, void*)in UserService.o
  "apache::thrift::TApplicationException::read(apache::thrift::protocol::TProtocol*)", referenced from:
      UserServiceClient::recv_add()      in UserService.o
      UserServiceClient::recv_get(User&)      in UserService.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status
1 楼 visoeclipse 2012-05-07  
通过你的说法, 我编译结果出现下面错误:
Type 'UserServiceProcessor' could not be resolved

这个是啥意思?

相关推荐

    thrift 的 java 和 python结合例子

    在这个"thrift的java和python结合例子"中,我们将探讨如何使用Thrift在Java和Python之间建立通信。 首先,Thrift通过定义接口描述文件(.thrift)来规范服务的接口。这个文件使用Thrift IDL(Interface Description...

    Thrift-java学习小结

    Thrift是一种远程过程调用(RPC)框架,它通过定义一种中间描述文件(.thrift),可以生成多种编程语言的代码,如Java、Python、C++等。这种跨语言的能力使得开发多语言服务变得简单,同时Thrift还提供了一种轻量级...

    thrift_java_demo和安装包

    - 跨语言:Thrift支持多种编程语言,如Java、Python、C++、PHP等,使得不同语言的服务可以无缝对接。 - 高效性:Thrift采用了高效的二进制传输协议,相比文本协议(如JSON、XML),在网络传输中更节省带宽和提高...

    Thrift简单调用demo代码

    2. **代码生成**:通过Thrift编译器,我们可以将`.thrift`文件转换为特定编程语言的代码,例如Java、Python或C++。这些生成的代码包括服务接口的抽象类、数据结构的类以及客户端和服务端的通信协议实现。 3. **...

    Thrift Java 服务器 客户端通信

    Thrift的主要目标是高效地在不同的编程语言之间进行数据序列化和远程过程调用(RPC)。它通过定义一种中间表示(IDL,Interface Description Language)来描述服务接口,然后自动生成相应的客户端和服务器端代码,...

    采用java操作thrift代码示例

    5. **创建客户端**:同样,使用生成的`MyService$Client.java`,创建一个Thrift客户端,连接到服务器并调用`sayHello`方法: ```java public class ThriftClient { public static void main(String[] args) ...

    使用wireshark抓取thrift协议接口调用

    生成的代码支持多种编程语言,如Java、Python、C++等,使得跨平台通信变得简单。 2. **Wireshark配置** - 安装Wireshark:首先确保你的系统上已经安装了Wireshark。如果尚未安装,可以从其官方网站下载适合你操作...

    Windows下QT使用Thrift的样例

    Thrift-0.10.0是这个样例中使用的版本,它支持C++、Java、Python等多种语言,并且具有良好的性能和稳定性。 Boost是一个流行的C++库集合,提供了许多用于提高C++效率和功能的工具。在这个样例中,Boost可能被用来...

    Thrift入门及Java实例演示

    1. **Thrift IDL**:Thrift的接口定义语言类似于C++或Java的接口,用于定义服务、结构体、异常和枚举等。例如,你可以定义一个简单的服务,包含若干个方法,然后在不同的语言中实现这些接口。 2. **服务生成**:...

    Python库 | thrift_pyi-0.2.0-py3-none-any.whl

    Thrift支持多种编程语言,包括但不限于Java、C++、Python、PHP、Ruby等,这使得跨语言的分布式系统开发变得更加便捷。在微服务架构和大型分布式系统中,Thrift是一个非常有价值的工具,因为它可以有效地降低不同语言...

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

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

    java 通过thrift-0.9.1读取hbase表数据

    然而,由于HBase的原生API是用Java编写的,对于非Java语言如Python、C++等,直接使用会比较复杂。这时,Apache Thrift就派上用场了。 Thrift是一个接口定义语言和跨语言的通信框架,它可以生成多种编程语言的代码,...

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

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

    thrift-java实例

    Thrift 支持多种编程语言,如 C++, Java, PHP, Python 等,使得在这些语言之间进行数据交换变得简单而高效。它提供了一种二进制协议,相比 JSON 或 XML,在性能和传输大小上有显著优势,特别适合大型系统的数据交互...

    thrift实现http协议案例

    Thrift的编译器会根据这个定义生成Java、Python、C++等语言的客户端和服务端代码。 在“thrift实现http协议案例”中,由于Thrift默认只支持基于TCP的socket通信,而我们需要实现HTTP协议,所以需要自定义处理。这里...

    thrift安装

    1. **跨语言性**:Thrift支持众多编程语言,如C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, Smalltalk等,使得服务的开发和调用可以在不同的语言环境中进行。 2. **高性能**:Thrift通过高效...

    thrift的使用介绍

    Thrift通过定义一种中间表示(IDL,Interface Definition Language)来描述服务接口,然后自动生成相应的客户端和服务器端代码,使得开发者可以轻松地在多种语言之间进行数据交换和服务调用。 **1. Thrift IDL** ...

    thrift vc2008版本静态库

    - Thrift 支持多种编程语言,如C++, Java, Python, PHP, Ruby等,使得跨语言服务开发变得简单。 - 它通过定义IDL(接口定义语言)文件来描述服务接口,然后自动生成客户端和服务端的代码。 2. **VC2008 静态库**...

    thrift样例操作实例

    例如,你可以编写一个`.thrift`文件来定义服务接口,然后使用这个编译器生成Java或C++的客户端和服务端代码。 `thrift-0.9.3.tar.gz`是Thrift的源码包,包含了编译器和其他相关工具。如果你需要在特定环境中构建...

Global site tag (gtag.js) - Google Analytics