您的位置:首页 > 运维架构 > Apache

利用apache Thrift 进行 node.js和 C++进程间通讯

2013-03-16 23:12 791 查看
Apache thift 是 facebook开发的一个支持跨语言进程通讯的软件框架.
下面说明node.js 和 C++如何借助于 它进行通讯.
1. 首先, 创建一个 thrift IDL 文件 my.thrift, 如下:

#!/usr/local/bin/thrift --gen cpp

namespace cpp Test

service Something {
i32 ping()
}
ping 是一个 node.js 和 C++ IPC的 接口.

2. 运行命令,创建出 C++文件:

thrift --gen cpp my.thrift
这时,会在当前目录下,生成一个 gen-cpp 目录和一些文件:

$ tree .
.
├── gen-cpp
│   ├── my_constants.cpp
│   ├── my_constants.h
│   ├── my_types.cpp
│   ├── my_types.h
│   ├── Something.cpp
│   ├── Something.h
│   └── Something_server.skeleton.cpp
└── my.thrift

1 directory, 8 files
自动生成了一个 server 文件 Something_server.skeleton.cpp.

运行下面的命令:

cp Something_server.skeleton.cpp Something_server.cpp
server文件内容如下:

$ cat Something_server.cpp
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "Something.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TBufferTransports.h>

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

using boost::shared_ptr;

using namespace  ::Test;

class SomethingHandler : virtual public SomethingIf {
public:
SomethingHandler() {
// Your initialization goes here
}

int32_t ping() {
// Your implementation goes here
printf("ping, server-side api is called\n");
}

};

int main(int argc, char **argv) {
int port = 9090;
shared_ptr<SomethingHandler> handler(new
SomethingHandler());
shared_ptr<TProcessor> processor(new
SomethingProcessor(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;
}


3. client 文件没有自动生成,需要手动写一个:

$ cat Something_client.cpp
#include "Something.h"  // As an example

#include <transport/TSocket.h>
#include <transport/TBufferTransports.h>
#include <protocol/TBinaryProtocol.h>

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

using namespace Test;

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
TBinaryProtocol(transport));

SomethingClient client(protocol);
transport->open();
printf("call ping
........\n");
client.ping();
transport->close();

return 0;
}


5.写一个makefile文件, 如下:

$ cat Makefile
GEN_SRC := Something.cpp my_constants.cpp my_types.cpp
GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))

THRIFT_DIR := /usr/local/include/thrift
BOOST_DIR := /usr/local/include

INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)

.PHONY: all clean

all: something_server something_client

%.o: %.cpp
$(CXX) -Wall -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H $(INC) -c $<
-o $@

something_server: Something_server.o $(GEN_OBJ)
$(CXX) $^ -o $@ -L/usr/local/lib -lthrift

something_client: Something_client.o $(GEN_OBJ)
$(CXX) $^ -o $@ -L/usr/local/lib -lthrift

clean:
$(RM) *.o something_server something_client


运行 make,会生成两个可执行文件: something_client 和 something_server
6.测试 C++之间 的 IPC:
$ ./something_server &
[1] 18211
$ ./something_client
call ping ........
ping, server-side api is called


7. 现在配置 node.js:

$ thrift  --gen js:node my.thrift


同样,生成一个 gen-nodejs的目录和一些文件:

$ tree gen-nodejs/
gen-nodejs/
├── my_types.js
└── Something.js

0 directories, 2 files


创建一个 client 文件如下:

$ cat client.js
var thrift = require('thrift');

var service = require('./Something.js')
ttypes = require('./my_types');

var connection = thrift.createConnection('localhost', 9090);

connection.on("error", function(err) {
console.error(err);
});

var client = thrift.createClient(service, connection);

client.ping();

connection.end();


执行npm命令,安装 thrift 库:

$ npm install thrift
npm http GET https://registry.npmjs.org/thrift npm http 304 https://registry.npmjs.org/thrift thrift@0.7.0 node_modules/thrift


因为, 目前,对于 node.js, TBufferedTransport的模式还不支持,所以要改一下 C++文件,把 TBufferedTransport改成 TframedTransport

改动后的文件如下:

$ cat Something_server.cpp
// This autogenerated skeleton file illustrates how to build a server.
// You should copy it to another filename to avoid overwriting it.

#include "Something.h"
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/server/TSimpleServer.h>
#include <thrift/transport/TServerSocket.h>
#include <thrift/transport/TTransportUtils.h>

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

using boost::shared_ptr;

using namespace  ::Test;

class SomethingHandler : virtual public SomethingIf {
public:
SomethingHandler() {
// Your initialization goes here
}

int32_t ping() {
// Your implementation goes here
printf("ping, Ha ha, you got it\n");
}

};

int main(int argc, char **argv) {
int port = 9090;
shared_ptr<SomethingHandler> handler(new
SomethingHandler());
shared_ptr<TProcessor> processor(new
SomethingProcessor(handler));
shared_ptr<TServerTransport> serverTransport(new
TServerSocket(port));
shared_ptr<TTransportFactory> transportFactory(new
TFramedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new
TBinaryProtocolFactory());

TSimpleServer server(processor, serverTransport, transportFactory,
protocolFactory);
printf("starting a server ..........\n");
server.serve();
return 0;
}


8.重新运行 make, 生成新的 server程序.
然后测试
$ ./something_server &
[1] 19532
$ node ./client.js
ping, Ha ha, you got it


P.S.

C++代码部分,参考了
http://wiki.apache.org/thrift 里面的示例代码.这个网址比较有用 ^^
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: