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

释放双眼,带上耳机,听听看~!

Apache thift 是 facebook开发的一个支持跨语言进程通讯的软件框架.

下面说明node.js 和 C++如何借助于 它进行通讯.

  1. 首先, 创建一个 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的 接口.

  1. 运行命令,创建出 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
  1. 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
  1. 现在配置 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++代码部分,参考了
 

http://wiki.apache.org/thrift

里面的示例代码.这个网址比较有用 ^^

给TA打赏
共{{data.count}}人
人已打赏
安全技术

DES 加密 解密

2021-8-18 16:36:11

安全技术

C++ 高性能服务器网络框架设计细节

2022-1-11 12:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索