在使用本内容前,需要安装 Thrift
首先编辑 一个接口文件 .thrift
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) }
运行如下命令:
# thrift -r --gen cpp demo.thrift
可以看到在当前目录下产生了一个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是跟业务相关的,是可以修改的,其余文件都是框架相关的。
// 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; }
可以看到,该文件只是一个框架,用户可以根据需要扩展该文件,笔者修改如下(蓝色部分为添加的代码,同时将文件改名为 serStorage_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 <thrift/protocol/TBinaryProtocol.h> #include <thrift/server/TSimpleServer.h> #include <thrift/transport/TServerSocket.h> #include <thrift/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; }
C++客户端实现
#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: 编译C++ 服务端和C++客户端
#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../gen-cpp -I${THRIFT_DIR} -L${LIB_DIR} -lthrift UserStorage_server.cpp ${GEN_SRC} client: CppClient.cpp g++ -o CppClient -I../gen-cpp -I${THRIFT_DIR} -L${LIB_DIR} -lthrift CppClient.cpp ${GEN_SRC} clean: $(RM) -r CppClient CppServer
Java客户端实现
到thrift-x.x.x/tutorial/java/src/拷贝:JavaClient.java
重命名为: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(); } } }
编译Java客户端需要使用Thrift Java 库,可以使用Maven
<dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.9.3</version> </dependency>
编译成功后便可以通讯了