nng-ruby 0.1.2 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +78 -45
- data/Gemfile +10 -10
- data/LICENSE +21 -21
- data/README.md +1201 -1200
- data/Rakefile +22 -22
- data/examples/pair.rb +48 -48
- data/examples/protobuf_advanced.rb +322 -322
- data/examples/protobuf_demo.rb +340 -340
- data/examples/protobuf_example.rb +374 -374
- data/examples/protobuf_simple.rb +191 -191
- data/examples/protobuf_thread.rb +236 -236
- data/examples/pubsub.rb +51 -51
- data/examples/reqrep.rb +54 -54
- data/ext/nng/extconf.rb +80 -71
- data/ext/nng/libnng.so.1.11.0 +0 -0
- data/ext/nng/nng.dll +0 -0
- data/lib/nng/errors.rb +48 -48
- data/lib/nng/ffi.rb +508 -445
- data/lib/nng/message.rb +151 -151
- data/lib/nng/protocols.rb +96 -96
- data/lib/nng/socket.rb +196 -196
- data/lib/nng/version.rb +5 -5
- data/lib/nng.rb +52 -52
- data/nng.gemspec +67 -67
- metadata +5 -4
- data/ext/nng/libnng.so.1.8.0 +0 -0
data/examples/protobuf_simple.rb
CHANGED
|
@@ -1,191 +1,191 @@
|
|
|
1
|
-
#!/usr/bin/env ruby
|
|
2
|
-
# frozen_string_literal: true
|
|
3
|
-
|
|
4
|
-
# NNG + Protocol Buffers 简单示例
|
|
5
|
-
# 演示如何在 NNG 通信中使用 Protobuf 序列化
|
|
6
|
-
|
|
7
|
-
require 'nng'
|
|
8
|
-
require 'google/protobuf'
|
|
9
|
-
|
|
10
|
-
puts "=" * 70
|
|
11
|
-
puts "NNG + Protocol Buffers 简单示例"
|
|
12
|
-
puts "=" * 70
|
|
13
|
-
puts
|
|
14
|
-
|
|
15
|
-
# ============================================================================
|
|
16
|
-
# 1. 定义 Protobuf 消息格式
|
|
17
|
-
# ============================================================================
|
|
18
|
-
|
|
19
|
-
puts "步骤 1: 定义 Protobuf 消息"
|
|
20
|
-
puts "-" * 70
|
|
21
|
-
|
|
22
|
-
# 定义请求消息
|
|
23
|
-
Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
24
|
-
add_file("request.proto", syntax: :proto3) do
|
|
25
|
-
add_message "Request" do
|
|
26
|
-
optional :id, :int32, 1
|
|
27
|
-
optional :rpc_method, :string, 2
|
|
28
|
-
optional :params, :string, 3
|
|
29
|
-
end
|
|
30
|
-
end
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# 定义响应消息
|
|
34
|
-
Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
35
|
-
add_file("response.proto", syntax: :proto3) do
|
|
36
|
-
add_message "Response" do
|
|
37
|
-
optional :id, :int32, 1
|
|
38
|
-
optional :status, :int32, 2
|
|
39
|
-
optional :message, :string, 3
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
Request = Google::Protobuf::DescriptorPool.generated_pool.lookup("Request").msgclass
|
|
45
|
-
Response = Google::Protobuf::DescriptorPool.generated_pool.lookup("Response").msgclass
|
|
46
|
-
|
|
47
|
-
puts "✅ Protobuf 消息定义完成"
|
|
48
|
-
puts
|
|
49
|
-
|
|
50
|
-
# ============================================================================
|
|
51
|
-
# 2. 序列化和反序列化测试
|
|
52
|
-
# ============================================================================
|
|
53
|
-
|
|
54
|
-
puts "步骤 2: 测试 Protobuf 序列化"
|
|
55
|
-
puts "-" * 70
|
|
56
|
-
|
|
57
|
-
# 创建请求对象
|
|
58
|
-
request = Request.new(
|
|
59
|
-
id: 12345,
|
|
60
|
-
rpc_method: "getUserInfo",
|
|
61
|
-
params: '{"user_id": 888}'
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
puts "原始请求对象:"
|
|
65
|
-
puts " ID: #{request.id}"
|
|
66
|
-
puts " Method: #{request.rpc_method}"
|
|
67
|
-
puts " Params: #{request.params}"
|
|
68
|
-
puts
|
|
69
|
-
|
|
70
|
-
# 序列化为二进制
|
|
71
|
-
binary_data = Request.encode(request)
|
|
72
|
-
puts "序列化结果:"
|
|
73
|
-
puts " 大小: #{binary_data.bytesize} bytes"
|
|
74
|
-
puts " 十六进制: #{binary_data.unpack('H*').first}"
|
|
75
|
-
puts
|
|
76
|
-
|
|
77
|
-
# 反序列化
|
|
78
|
-
decoded_request = Request.decode(binary_data)
|
|
79
|
-
puts "反序列化结果:"
|
|
80
|
-
puts " ID: #{decoded_request.id}"
|
|
81
|
-
puts " Method: #{decoded_request.rpc_method}"
|
|
82
|
-
puts " Params: #{decoded_request.params}"
|
|
83
|
-
puts
|
|
84
|
-
|
|
85
|
-
# ============================================================================
|
|
86
|
-
# 3. 使用进程模拟客户端-服务器通信
|
|
87
|
-
# ============================================================================
|
|
88
|
-
|
|
89
|
-
puts "步骤 3: NNG + Protobuf 通信演示"
|
|
90
|
-
puts "-" * 70
|
|
91
|
-
|
|
92
|
-
url = "tcp://127.0.0.1:15557"
|
|
93
|
-
|
|
94
|
-
# 创建服务器进程
|
|
95
|
-
server_pid = fork do
|
|
96
|
-
begin
|
|
97
|
-
server = NNG::Socket.new(:pair1)
|
|
98
|
-
server.listen(url)
|
|
99
|
-
puts "[服务器] 监听: #{url}"
|
|
100
|
-
|
|
101
|
-
# 接收请求
|
|
102
|
-
request_data = server.recv
|
|
103
|
-
puts "[服务器] 收到 #{request_data.bytesize} bytes 数据"
|
|
104
|
-
|
|
105
|
-
# 反序列化请求
|
|
106
|
-
request = Request.decode(request_data)
|
|
107
|
-
puts "[服务器] 解析请求:"
|
|
108
|
-
puts "[服务器] ID: #{request.id}"
|
|
109
|
-
puts "[服务器] Method: #{request.rpc_method}"
|
|
110
|
-
puts "[服务器] Params: #{request.params}"
|
|
111
|
-
|
|
112
|
-
# 创建响应
|
|
113
|
-
response = Response.new(
|
|
114
|
-
id: request.id,
|
|
115
|
-
status: 200,
|
|
116
|
-
message: "处理成功: #{request.rpc_method}"
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
# 序列化并发送
|
|
120
|
-
response_data = Response.encode(response)
|
|
121
|
-
server.send(response_data)
|
|
122
|
-
puts "[服务器] 发送响应 #{response_data.bytesize} bytes"
|
|
123
|
-
|
|
124
|
-
server.close
|
|
125
|
-
rescue => e
|
|
126
|
-
puts "[服务器] 错误: #{e.message}"
|
|
127
|
-
end
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
# 等待服务器启动
|
|
131
|
-
sleep 0.5
|
|
132
|
-
|
|
133
|
-
# 客户端
|
|
134
|
-
begin
|
|
135
|
-
client = NNG::Socket.new(:pair1)
|
|
136
|
-
client.dial(url)
|
|
137
|
-
puts "[客户端] 连接: #{url}"
|
|
138
|
-
|
|
139
|
-
# 创建请求
|
|
140
|
-
request = Request.new(
|
|
141
|
-
id: 99999,
|
|
142
|
-
rpc_method: "getContacts",
|
|
143
|
-
params: '{"limit": 100}'
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
# 序列化并发送
|
|
147
|
-
request_data = Request.encode(request)
|
|
148
|
-
puts "[客户端] 发送请求 #{request_data.bytesize} bytes"
|
|
149
|
-
client.send(request_data)
|
|
150
|
-
|
|
151
|
-
# 接收响应
|
|
152
|
-
response_data = client.recv
|
|
153
|
-
puts "[客户端] 收到响应 #{response_data.bytesize} bytes"
|
|
154
|
-
|
|
155
|
-
# 反序列化
|
|
156
|
-
response = Response.decode(response_data)
|
|
157
|
-
puts "[客户端] 解析响应:"
|
|
158
|
-
puts "[客户端] ID: #{response.id}"
|
|
159
|
-
puts "[客户端] Status: #{response.status}"
|
|
160
|
-
puts "[客户端] Message: #{response.message}"
|
|
161
|
-
|
|
162
|
-
client.close
|
|
163
|
-
rescue => e
|
|
164
|
-
puts "[客户端] 错误: #{e.message}"
|
|
165
|
-
puts e.backtrace.first(3)
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
# 等待服务器进程结束
|
|
169
|
-
Process.wait(server_pid)
|
|
170
|
-
|
|
171
|
-
puts
|
|
172
|
-
puts "=" * 70
|
|
173
|
-
puts "✅ 示例完成"
|
|
174
|
-
puts "=" * 70
|
|
175
|
-
puts
|
|
176
|
-
puts "关键代码:"
|
|
177
|
-
puts
|
|
178
|
-
puts " # 序列化"
|
|
179
|
-
puts " binary_data = Request.encode(request)"
|
|
180
|
-
puts " socket.send(binary_data)"
|
|
181
|
-
puts
|
|
182
|
-
puts " # 反序列化"
|
|
183
|
-
puts " binary_data = socket.recv"
|
|
184
|
-
puts " request = Request.decode(binary_data)"
|
|
185
|
-
puts
|
|
186
|
-
puts "优势:"
|
|
187
|
-
puts " ✅ 类型安全的消息定义"
|
|
188
|
-
puts " ✅ 高效的二进制序列化 (~50% 比 JSON 小)"
|
|
189
|
-
puts " ✅ 跨语言兼容 (Python, Java, Go, C++ 等)"
|
|
190
|
-
puts " ✅ 向后兼容的版本演进"
|
|
191
|
-
puts
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# NNG + Protocol Buffers 简单示例
|
|
5
|
+
# 演示如何在 NNG 通信中使用 Protobuf 序列化
|
|
6
|
+
|
|
7
|
+
require 'nng'
|
|
8
|
+
require 'google/protobuf'
|
|
9
|
+
|
|
10
|
+
puts "=" * 70
|
|
11
|
+
puts "NNG + Protocol Buffers 简单示例"
|
|
12
|
+
puts "=" * 70
|
|
13
|
+
puts
|
|
14
|
+
|
|
15
|
+
# ============================================================================
|
|
16
|
+
# 1. 定义 Protobuf 消息格式
|
|
17
|
+
# ============================================================================
|
|
18
|
+
|
|
19
|
+
puts "步骤 1: 定义 Protobuf 消息"
|
|
20
|
+
puts "-" * 70
|
|
21
|
+
|
|
22
|
+
# 定义请求消息
|
|
23
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
24
|
+
add_file("request.proto", syntax: :proto3) do
|
|
25
|
+
add_message "Request" do
|
|
26
|
+
optional :id, :int32, 1
|
|
27
|
+
optional :rpc_method, :string, 2
|
|
28
|
+
optional :params, :string, 3
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# 定义响应消息
|
|
34
|
+
Google::Protobuf::DescriptorPool.generated_pool.build do
|
|
35
|
+
add_file("response.proto", syntax: :proto3) do
|
|
36
|
+
add_message "Response" do
|
|
37
|
+
optional :id, :int32, 1
|
|
38
|
+
optional :status, :int32, 2
|
|
39
|
+
optional :message, :string, 3
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
Request = Google::Protobuf::DescriptorPool.generated_pool.lookup("Request").msgclass
|
|
45
|
+
Response = Google::Protobuf::DescriptorPool.generated_pool.lookup("Response").msgclass
|
|
46
|
+
|
|
47
|
+
puts "✅ Protobuf 消息定义完成"
|
|
48
|
+
puts
|
|
49
|
+
|
|
50
|
+
# ============================================================================
|
|
51
|
+
# 2. 序列化和反序列化测试
|
|
52
|
+
# ============================================================================
|
|
53
|
+
|
|
54
|
+
puts "步骤 2: 测试 Protobuf 序列化"
|
|
55
|
+
puts "-" * 70
|
|
56
|
+
|
|
57
|
+
# 创建请求对象
|
|
58
|
+
request = Request.new(
|
|
59
|
+
id: 12345,
|
|
60
|
+
rpc_method: "getUserInfo",
|
|
61
|
+
params: '{"user_id": 888}'
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
puts "原始请求对象:"
|
|
65
|
+
puts " ID: #{request.id}"
|
|
66
|
+
puts " Method: #{request.rpc_method}"
|
|
67
|
+
puts " Params: #{request.params}"
|
|
68
|
+
puts
|
|
69
|
+
|
|
70
|
+
# 序列化为二进制
|
|
71
|
+
binary_data = Request.encode(request)
|
|
72
|
+
puts "序列化结果:"
|
|
73
|
+
puts " 大小: #{binary_data.bytesize} bytes"
|
|
74
|
+
puts " 十六进制: #{binary_data.unpack('H*').first}"
|
|
75
|
+
puts
|
|
76
|
+
|
|
77
|
+
# 反序列化
|
|
78
|
+
decoded_request = Request.decode(binary_data)
|
|
79
|
+
puts "反序列化结果:"
|
|
80
|
+
puts " ID: #{decoded_request.id}"
|
|
81
|
+
puts " Method: #{decoded_request.rpc_method}"
|
|
82
|
+
puts " Params: #{decoded_request.params}"
|
|
83
|
+
puts
|
|
84
|
+
|
|
85
|
+
# ============================================================================
|
|
86
|
+
# 3. 使用进程模拟客户端-服务器通信
|
|
87
|
+
# ============================================================================
|
|
88
|
+
|
|
89
|
+
puts "步骤 3: NNG + Protobuf 通信演示"
|
|
90
|
+
puts "-" * 70
|
|
91
|
+
|
|
92
|
+
url = "tcp://127.0.0.1:15557"
|
|
93
|
+
|
|
94
|
+
# 创建服务器进程
|
|
95
|
+
server_pid = fork do
|
|
96
|
+
begin
|
|
97
|
+
server = NNG::Socket.new(:pair1)
|
|
98
|
+
server.listen(url)
|
|
99
|
+
puts "[服务器] 监听: #{url}"
|
|
100
|
+
|
|
101
|
+
# 接收请求
|
|
102
|
+
request_data = server.recv
|
|
103
|
+
puts "[服务器] 收到 #{request_data.bytesize} bytes 数据"
|
|
104
|
+
|
|
105
|
+
# 反序列化请求
|
|
106
|
+
request = Request.decode(request_data)
|
|
107
|
+
puts "[服务器] 解析请求:"
|
|
108
|
+
puts "[服务器] ID: #{request.id}"
|
|
109
|
+
puts "[服务器] Method: #{request.rpc_method}"
|
|
110
|
+
puts "[服务器] Params: #{request.params}"
|
|
111
|
+
|
|
112
|
+
# 创建响应
|
|
113
|
+
response = Response.new(
|
|
114
|
+
id: request.id,
|
|
115
|
+
status: 200,
|
|
116
|
+
message: "处理成功: #{request.rpc_method}"
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# 序列化并发送
|
|
120
|
+
response_data = Response.encode(response)
|
|
121
|
+
server.send(response_data)
|
|
122
|
+
puts "[服务器] 发送响应 #{response_data.bytesize} bytes"
|
|
123
|
+
|
|
124
|
+
server.close
|
|
125
|
+
rescue => e
|
|
126
|
+
puts "[服务器] 错误: #{e.message}"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# 等待服务器启动
|
|
131
|
+
sleep 0.5
|
|
132
|
+
|
|
133
|
+
# 客户端
|
|
134
|
+
begin
|
|
135
|
+
client = NNG::Socket.new(:pair1)
|
|
136
|
+
client.dial(url)
|
|
137
|
+
puts "[客户端] 连接: #{url}"
|
|
138
|
+
|
|
139
|
+
# 创建请求
|
|
140
|
+
request = Request.new(
|
|
141
|
+
id: 99999,
|
|
142
|
+
rpc_method: "getContacts",
|
|
143
|
+
params: '{"limit": 100}'
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
# 序列化并发送
|
|
147
|
+
request_data = Request.encode(request)
|
|
148
|
+
puts "[客户端] 发送请求 #{request_data.bytesize} bytes"
|
|
149
|
+
client.send(request_data)
|
|
150
|
+
|
|
151
|
+
# 接收响应
|
|
152
|
+
response_data = client.recv
|
|
153
|
+
puts "[客户端] 收到响应 #{response_data.bytesize} bytes"
|
|
154
|
+
|
|
155
|
+
# 反序列化
|
|
156
|
+
response = Response.decode(response_data)
|
|
157
|
+
puts "[客户端] 解析响应:"
|
|
158
|
+
puts "[客户端] ID: #{response.id}"
|
|
159
|
+
puts "[客户端] Status: #{response.status}"
|
|
160
|
+
puts "[客户端] Message: #{response.message}"
|
|
161
|
+
|
|
162
|
+
client.close
|
|
163
|
+
rescue => e
|
|
164
|
+
puts "[客户端] 错误: #{e.message}"
|
|
165
|
+
puts e.backtrace.first(3)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# 等待服务器进程结束
|
|
169
|
+
Process.wait(server_pid)
|
|
170
|
+
|
|
171
|
+
puts
|
|
172
|
+
puts "=" * 70
|
|
173
|
+
puts "✅ 示例完成"
|
|
174
|
+
puts "=" * 70
|
|
175
|
+
puts
|
|
176
|
+
puts "关键代码:"
|
|
177
|
+
puts
|
|
178
|
+
puts " # 序列化"
|
|
179
|
+
puts " binary_data = Request.encode(request)"
|
|
180
|
+
puts " socket.send(binary_data)"
|
|
181
|
+
puts
|
|
182
|
+
puts " # 反序列化"
|
|
183
|
+
puts " binary_data = socket.recv"
|
|
184
|
+
puts " request = Request.decode(binary_data)"
|
|
185
|
+
puts
|
|
186
|
+
puts "优势:"
|
|
187
|
+
puts " ✅ 类型安全的消息定义"
|
|
188
|
+
puts " ✅ 高效的二进制序列化 (~50% 比 JSON 小)"
|
|
189
|
+
puts " ✅ 跨语言兼容 (Python, Java, Go, C++ 等)"
|
|
190
|
+
puts " ✅ 向后兼容的版本演进"
|
|
191
|
+
puts
|