Apache thift 是 facebook开发的一个支持跨语言进程通讯的软件框架.
下面说明node.js 和 C++如何借助于 它进行通讯.
-
首先, 创建一个 thrift IDL 文件 my.thrift, 如下:
1
2
3
4
5
6
7
8
9 1#!/usr/local/bin/thrift --gen cpp
2
3namespace cpp Test
4
5service Something {
6 i32 ping()
7}
8
9
ping 是一个 node.js 和 C++ IPC的 接口.
-
运行命令,创建出 C++文件:
1
2 1thrift --gen cpp my.thrift
2
这时,会在当前目录下,生成一个 gen-cpp 目录和一些文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14 1$ tree .
2.
3├── gen-cpp
4│ ├── my_constants.cpp
5│ ├── my_constants.h
6│ ├── my_types.cpp
7│ ├── my_types.h
8│ ├── Something.cpp
9│ ├── Something.h
10│ └── Something_server.skeleton.cpp
11└── my.thrift
12
131 directory, 8 files
14
自动生成了一个 server 文件 Something_server.skeleton.cpp.
运行下面的命令:
1
2 1cp Something_server.skeleton.cpp Something_server.cpp
2
1
2 1server文件内容如下:
2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 1$ cat Something_server.cpp
2// This autogenerated skeleton file illustrates how to build a server.
3// You should copy it to another filename to avoid overwriting it.
4
5#include "Something.h"
6#include <thrift/protocol/TBinaryProtocol.h>
7#include <thrift/server/TSimpleServer.h>
8#include <thrift/transport/TServerSocket.h>
9#include <thrift/transport/TBufferTransports.h>
10
11using namespace ::apache::thrift;
12using namespace ::apache::thrift::protocol;
13using namespace ::apache::thrift::transport;
14using namespace ::apache::thrift::server;
15
16using boost::shared_ptr;
17
18using namespace ::Test;
19
20class SomethingHandler : virtual public SomethingIf {
21 public:
22 SomethingHandler() {
23 // Your initialization goes here
24 }
25
26 int32_t ping() {
27 // Your implementation goes here
28 printf("ping, server-side api is called\n");
29 }
30
31};
32
33int main(int argc, char **argv) {
34 int port = 9090;
35 shared_ptr<SomethingHandler> handler(new
36SomethingHandler());
37 shared_ptr<TProcessor> processor(new
38SomethingProcessor(handler));
39 shared_ptr<TServerTransport> serverTransport(new
40TServerSocket(port));
41 shared_ptr<TTransportFactory> transportFactory(new
42TBufferedTransportFactory());
43 shared_ptr<TProtocolFactory> protocolFactory(new
44TBinaryProtocolFactory());
45
46 TSimpleServer server(processor, serverTransport, transportFactory,
47protocolFactory);
48 server.serve();
49 return 0;
50}
51
52
-
client 文件没有自动生成,需要手动写一个:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 1$ cat Something_client.cpp
2#include "Something.h" // As an example
3
4#include <transport/TSocket.h>
5#include <transport/TBufferTransports.h>
6#include <protocol/TBinaryProtocol.h>
7
8using namespace apache::thrift;
9using namespace apache::thrift::protocol;
10using namespace apache::thrift::transport;
11
12using namespace Test;
13
14int main(int argc, char **argv) {
15 boost::shared_ptr<TSocket> socket(new
16TSocket("localhost", 9090));
17 boost::shared_ptr<TTransport> transport(new
18TBufferedTransport(socket));
19 boost::shared_ptr<TProtocol> protocol(new
20TBinaryProtocol(transport));
21
22 SomethingClient client(protocol);
23 transport->open();
24 printf("call ping
25........\n");
26 client.ping();
27 transport->close();
28
29 return 0;
30}
31
32
33
5.写一个makefile文件, 如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 1$ cat Makefile
2GEN_SRC := Something.cpp my_constants.cpp my_types.cpp
3GEN_OBJ := $(patsubst %.cpp,%.o, $(GEN_SRC))
4
5THRIFT_DIR := /usr/local/include/thrift
6BOOST_DIR := /usr/local/include
7
8INC := -I$(THRIFT_DIR) -I$(BOOST_DIR)
9
10.PHONY: all clean
11
12all: something_server something_client
13
14%.o: %.cpp
15 $(CXX) -Wall -DHAVE_INTTYPES_H -DHAVE_NETINET_IN_H $(INC) -c $<
16-o $@
17
18something_server: Something_server.o $(GEN_OBJ)
19 $(CXX) $^ -o $@ -L/usr/local/lib -lthrift
20
21something_client: Something_client.o $(GEN_OBJ)
22 $(CXX) $^ -o $@ -L/usr/local/lib -lthrift
23
24clean:
25 $(RM) *.o something_server something_client
26
运行 make,会生成两个可执行文件: something_client 和 something_server
6.测试 C++之间 的 IPC:
1
2
3
4
5
6
7 1$ ./something_server &
2[1] 18211
3$ ./something_client
4call ping ........
5ping, server-side api is called
6
7
-
现在配置 node.js:
1
2 1$ thrift --gen js:node my.thrift
2
同样,生成一个 gen-nodejs的目录和一些文件:
1
2
3
4
5
6
7 1$ tree gen-nodejs/
2gen-nodejs/
3├── my_types.js
4└── Something.js
5
60 directories, 2 files
7
创建一个 client 文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 1$ cat client.js
2var thrift = require('thrift');
3
4var service = require('./Something.js')
5ttypes = require('./my_types');
6
7
8var connection = thrift.createConnection('localhost', 9090);
9
10connection.on("error", function(err) {
11 console.error(err);
12});
13
14var client = thrift.createClient(service, connection);
15
16client.ping();
17
18connection.end();
19
20
执行npm命令,安装 thrift 库:
1
2
3
4
5 1$ npm install thrift
2npm http GET https://registry.npmjs.org/thrift
3npm http 304 https://registry.npmjs.org/thrift
4thrift@0.7.0 node_modules/thrift
5
因为, 目前,对于 node.js, TBufferedTransport的模式还不支持,所以要改一下 C++文件,把 TBufferedTransport改成 TframedTransport
改动后的文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 1$ cat Something_server.cpp
2// This autogenerated skeleton file illustrates how to build a server.
3// You should copy it to another filename to avoid overwriting it.
4
5#include "Something.h"
6#include <thrift/protocol/TBinaryProtocol.h>
7#include <thrift/server/TSimpleServer.h>
8#include <thrift/transport/TServerSocket.h>
9#include <thrift/transport/TTransportUtils.h>
10
11using namespace ::apache::thrift;
12using namespace ::apache::thrift::protocol;
13using namespace ::apache::thrift::transport;
14using namespace ::apache::thrift::server;
15
16using boost::shared_ptr;
17
18using namespace ::Test;
19
20class SomethingHandler : virtual public SomethingIf {
21 public:
22 SomethingHandler() {
23 // Your initialization goes here
24 }
25
26 int32_t ping() {
27 // Your implementation goes here
28 printf("ping, Ha ha, you got it\n");
29 }
30
31};
32
33int main(int argc, char **argv) {
34 int port = 9090;
35 shared_ptr<SomethingHandler> handler(new
36SomethingHandler());
37 shared_ptr<TProcessor> processor(new
38SomethingProcessor(handler));
39 shared_ptr<TServerTransport> serverTransport(new
40TServerSocket(port));
41 shared_ptr<TTransportFactory> transportFactory(new
42TFramedTransportFactory());
43 shared_ptr<TProtocolFactory> protocolFactory(new
44TBinaryProtocolFactory());
45
46 TSimpleServer server(processor, serverTransport, transportFactory,
47protocolFactory);
48printf("starting a server ..........\n");
49 server.serve();
50 return 0;
51}
52
8.重新运行 make, 生成新的 server程序.
然后测试
1
2
3
4
5
6 1$ ./something_server &
2[1] 19532
3$ node ./client.js
4ping, Ha ha, you got it
5
6
P.S.
C++代码部分,参考了
里面的示例代码.这个网址比较有用 ^^