thrift C++做server, C++,python, java做Client例子

来源:互联网 发布:eve大鲸鱼数据 编辑:程序博客网 时间:2024/05/20 05:03
一、安装
我机器上已经安装好了 thrift-0.9.1

二、示例
编辑demo.thrift文件,内容如下:
struct UserProfile{
        1:i32 id, //注意这里是逗号,而不是分号
        2:string name,
        3:string blurb
} //这里没有分号
 
service UserStorage{
        void store(1: UserProfile user), //注意这里是逗号,而不是分号
        UserProfile getUser(1: i32 uid)
}
 
运行如下命令
cloud1:~/test/thrift/demo # thrift -r --gen cpp demo.thrift 
cloud1:~/test/thrift/demo # ls
demo.thrift  gen-cpp
可以看到在当前目录下产生了一个gen-cpp的目录,该目录下即以上命令产生的文件:
UserStorage.cpp
UserStorage.h
UserStorage_server.skeleton.cpp
demo_constants.cpp
demo_constants.h
demo_types.cpp
demo_types.h

注意:在以上文件中,只有UserStorage_server.skeleton.cpp是跟业务相关的,是可以修改的,其余文件都是框架相关的。
UserStorage_server_skeleton.cpp文件内容如下:
 
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
 
#include "UserStorage.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <map>
 
using namespace std;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
 
using boost::shared_ptr;
 
class UserStorageHandler : virtual public UserStorageIf {
 public:
  UserStorageHandler() {
    // Your initialization goes here
  }
 
  void store(const UserProfile& user) {
    // Your implementation goes here
    printf("store\n");
  }
 
  void getUser(UserProfile& _return, const int32_t uid) {
    // Your implementation goes here
    printf("getUser\n");
  }
};
 
int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<UserStorageHandler> handler(new UserStorageHandler());
  shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
 
  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

可以看到,该文件只是一个框架,用户可以根据需要扩展该文件,笔者修改如下(蓝色部分为添加的代码,同时将文件改名为UserStorage_server.cpp):
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.
#include "UserStorage.h"
#include <protocol/TBinaryProtocol.h>
#include <server/TSimpleServer.h>
#include <transport/TServerSocket.h>
#include <transport/TBufferTransports.h>
#include <map>
using namespace std;
using namespace ::apache::thrift;
using namespace ::apache::thrift::protocol;
using namespace ::apache::thrift::transport;
using namespace ::apache::thrift::server;
using boost::shared_ptr;
class UserStorageHandler : virtual public UserStorageIf {
 public:
  UserStorageHandler() {
    // Your initialization goes here
  }
  void store(const UserProfile& user) {
    // Your implementation goes here
    log[user.id] = user; //实际的保存操作
    printf("store\n");
  }
  void getUser(UserProfile& _return, const int32_t uid) {
    // Your implementation goes here
        _return = log[uid]; //实际获取操作,注意:在实际生产中,这里还需要异常处理
    printf("getUser\n");
  }
  //增加成员变量,用户保存用户数据,为了简单起见,这里只将数据保存在内存,当然可以可以保存在数据库、文件等等,主要注意,如果保存在其他介质的话
  //在初始化的时候记得加载进内存或者打开访问句柄
  protected:
        map<int32_t, UserProfile> log;
};
int main(int argc, char **argv) {
  int port = 9090;
  shared_ptr<UserStorageHandler> handler(new UserStorageHandler());
  shared_ptr<TProcessor> processor(new UserStorageProcessor(handler));
  shared_ptr<TServerTransport> serverTransport(new TServerSocket(port));
  shared_ptr<TTransportFactory> transportFactory(new TBufferedTransportFactory());
  shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
  TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory);
  server.serve();
  return 0;
}

可以看到以上程序还包括一个简单的服务端代码,问了进行测试,笔者从thrift/tutorial/cpp/目录下copy了一个客户端代码和Makefile
修改如下:
CppClient.cpp (蓝色部分为客户化代码) 
 
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <protocol/TBinaryProtocol.h>
#include <transport/TSocket.h>
#include <transport/TTransportUtils.h>
#include "UserStorage.h"
using namespace std;
using namespace apache::thrift;
using namespace apache::thrift::protocol;
using namespace apache::thrift::transport;
using namespace boost;
int main(int argc, char** argv) {
  shared_ptr<TTransport> socket(new TSocket("localhost", 9090));
  shared_ptr<TTransport> transport(new TBufferedTransport(socket));
  shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
  UserStorageClient client(protocol);
  try {
    transport->open();
        UserProfile user;
        user.id = 1;
        user.name = "liqb";
        user.blurb = "aaaaaa";
        client.store(user);
        UserProfile user2;
        client.getUser(user2, 1);
        printf("user.id = %d user.name = %s user.blurb = %s\n", user2.id, user2.name.c_str(), user2.blurb.c_str());
    transport->close();
  } catch (TException &tx) {
    printf("ERROR: %s\n", tx.what());
  }
}
 
Makefile
 
BOOST_DIR = /usr/local/boost/include/boost-1_33_1/
THRIFT_DIR = /usr/local/include/thrift
LIB_DIR = /usr/local/lib
GEN_SRC = UserStorage.cpp demo_constants.cpp demo_types.cpp
default: server client
server: UserStorage_server.cpp
        g++ -o CppServer -I${THRIFT_DIR} -I${BOOST_DIR}  -I../gen-cpp -L${LIB_DIR} -lthrift UserStorage_server.cpp ${GEN_SRC}
client: CppClient.cpp
        g++ -o CppClient -I${THRIFT_DIR} -I${BOOST_DIR}  -I../gen-cpp -L${LIB_DIR} -lthrift CppClient.cpp ${GEN_SRC}
clean:
        $(RM) -r CppClient CppServer
 
编译之后产生CppServer 和CppClient 两个可执行程序,分别运行CppServer 和CppClient,即可以看到测试结果。
先运行服务器:
cloud1:~/test/thrift/demo/gen-cpp # ./CppServer 
再执行客户端:
cloud1:~/test/thrift/demo/gen-cpp # ./CppClient 
user.id = 1 user.name = liqb user.blurb = aaaaaa
cloud1:~/test/thrift/demo/gen-cpp # 

服务器上显示:
cloud1:~/test/thrift/demo/gen-cpp # ./CppServer 
store
getUser

Python 版客户端:
thrift/tutorial/
下拷:PythonClient.py 略做修改:
cloud1:~/test/thrift/demo # vi PythonClient.py 
  1 #!/usr/bin/env python
  2 
  3 #
  4 # Licensed to the Apache Software Foundation (ASF) under one
  5 # or more contributor license agreements. See the NOTICE file
#!/usr/bin/env python

#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

import sys, glob
sys.path.append('gen-py')
#sys.path.insert(0, glob.glob('../../lib/py/build/lib.*')[0])

from demo import UserStorage 
from demo.ttypes import *

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

try:

    # Make socket
    transport = TSocket.TSocket('localhost', 9090)

    # Buffering is critical. Raw sockets are very slow
    transport = TTransport.TBufferedTransport(transport)

    # Wrap in a protocol
    protocol = TBinaryProtocol.TBinaryProtocol(transport)

    # Create a client to use the protocol encoder
    client = UserStorage.Client(protocol)

    # Connect!
    transport.open()

    try:
        u1 = UserProfile()  
        u1.id=456  
        u1.name='nick'  
        u1.blurb='test bbb'  
        client.store(u1) 
        print 'store done!'
    except InvalidOperation, io: 
        print 'InvalidOperation: %r' % io


    u = client.getUser(123)  
    print 'id=%s name=%s blurb=%s' %(u.id,u.name,u.blurb)

    # Close!
    transport.close()

except Thrift.TException, tx:
    print '%s' % (tx.message)

cloud1:~/test/thrift/demo # python PythonClient.py 
store done!
id=123 name=jason blurb=test aaa
cloud1:~/test/thrift/demo # 

Java 版客户端:
thrift-0.9.1/tutorial/java/src/ 
下拷:JavaClient.java 做修改:
重命名为:UserProfileClient.java

cloud1:~/test/thrift/demo # vi UserProfileClient.java 

import org.apache.thrift.TException;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TTransport;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TSSLTransportFactory.TSSLTransportParameters;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;

public class UserProfileClient {
  public static void main(String [] args) {

    /*if (args.length != 1) {
      System.out.println("Please enter 'simple' or 'secure'");
      System.exit(0);
    }  */ 

    try {
      TTransport transport;
      //if (args[0].contains("simple")) {
        transport = new TSocket("localhost", 9090);
        transport.open();
      //}   
      //else {
        /*  
         * Similar to the server, you can use the parameters to setup client parameters or
         * use the default settings. On the client side, you will need a TrustStore which
         * contains the trusted certificate along with the public key. 
         * For this example it's a self-signed cert. 
         */
        //TSSLTransportParameters params = new TSSLTransportParameters();
        //params.setTrustStore("../../lib/java/test/.truststore", "thrift", "SunX509", "JKS");
        /*  
         * Get a client transport instead of a server transport. The connection is opened on
         * invocation of the factory method, no need to specifically call open()
         */
        //transport = TSSLTransportFactory.getClientSocket("localhost", 9091, 0, params);
      //}   

      TProtocol protocol = new  TBinaryProtocol(transport);
      UserStorage.Client client = new UserStorage.Client(protocol);

      int uid=123;
      System.out.println(client.getUser(uid));

      UserProfile u = new UserProfile();
      u.id=999;
      u.name="kaining";
      u.blurb="test 999"; 
      client.store(u);

      transport.close();
    } catch (TException x) {
      x.printStackTrace();
    }   
  }
}

cloud1:~/test/thrift/demo # cat compile.sh 
#!/bin/sh
export CLASS_PATH_JAVA=""

for i in /usr/local/lib/*.jar
do
        if [ "x${CLASS_PATH_JAVA}" == "x" ]
        then
                export CLASS_PATH_JAVA=$i
                continue
        fi
        export CLASS_PATH_JAVA=${CLASS_PATH_JAVA}:$i
#echo $i
done

echo "$CLASS_PATH_JAVA"
javac -classpath $CLASS_PATH_JAVA UserProfileClient.java ./gen-java/*.java
cloud1:~/test/thrift/demo # 
cloud1:~/test/thrift/demo # cat run.sh 
#!/bin/sh
export CLASS_PATH_JAVA=""

for i in /usr/local/lib/*.jar
do
        if [ "x${CLASS_PATH_JAVA}" == "x" ]
        then
                export CLASS_PATH_JAVA=.:$i
                continue
        fi
        export CLASS_PATH_JAVA=${CLASS_PATH_JAVA}:$i
done

#echo "$CLASS_PATH_JAVA"
java -cp $CLASS_PATH_JAVA:./gen-java UserProfileClient
cloud1:~/test/thrift/demo # 

编译,执行compile.sh
cloud1:~/test/thrift/demo # ./compile.sh 
/usr/local/lib/commons-codec-1.6.jar:/usr/local/lib/commons-lang3-3.1.jar:/usr/local/lib/commons-logging-1.1.1.jar:/usr/local/lib/httpclient-4.2.5.jar:/usr/local/lib/httpcore-4.2.4.jar:/usr/local/lib/junit-4.4.jar:/usr/local/lib/libthrift-0.9.1-javadoc.jar:/usr/local/lib/libthrift-0.9.1.jar:/usr/local/lib/log4j-1.2.14.jar:/usr/local/lib/servlet-api-2.5.jar:/usr/local/lib/slf4j-api-1.5.8.jar:/usr/local/lib/slf4j-log4j12-1.5.8.jar
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
cloud1:~/test/thrift/demo #

运行,执行run.sh
cloud1:~/test/thrift/demo # ./run.sh 
UserProfile(id:123, name:jason, blurb:test aaa)
cloud1:~/test/thrift/demo # 

参考:
http://blog.chinaunix.net/uid-20808006-id-1642643.html
http://jinghong.iteye.com/blog/1222713
0 0