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.
@@ -1,322 +1,322 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- # NNG + Protocol Buffers 高级示例
5
- # 使用 .proto 文件和复杂的消息嵌套
6
-
7
- require 'nng'
8
- require 'google/protobuf'
9
-
10
- puts "=" * 70
11
- puts "NNG + Protocol Buffers 高级示例"
12
- puts "使用 .proto 文件和消息嵌套"
13
- puts "=" * 70
14
- puts
15
-
16
- # ============================================================================
17
- # 1. 从 .proto 文件生成 Ruby 代码 (编译时)
18
- # ============================================================================
19
-
20
- puts "说明: 使用 .proto 文件"
21
- puts "-" * 70
22
- puts
23
- puts "实际项目中应该使用 protoc 编译 .proto 文件:"
24
- puts " $ protoc --ruby_out=. proto/message.proto"
25
- puts
26
- puts "本示例直接在 Ruby 中定义消息 (等效于编译后的代码)"
27
- puts
28
-
29
- # 定义消息 (等效于从 message.proto 编译生成)
30
- Google::Protobuf::DescriptorPool.generated_pool.build do
31
- add_file("message.proto", syntax: :proto3) do
32
- # RPC 请求
33
- add_message "RpcRequest" do
34
- optional :func_code, :int32, 1
35
- optional :data, :bytes, 2
36
- optional :timestamp, :int64, 3
37
- optional :request_id, :string, 4
38
- end
39
-
40
- # RPC 响应
41
- add_message "RpcResponse" do
42
- optional :status, :int32, 1
43
- optional :data, :bytes, 2
44
- optional :error_msg, :string, 3
45
- optional :request_id, :string, 4
46
- end
47
-
48
- # 用户
49
- add_message "User" do
50
- optional :id, :int32, 1
51
- optional :name, :string, 2
52
- optional :email, :string, 3
53
- repeated :tags, :string, 4
54
- end
55
-
56
- # 联系人
57
- add_message "Contact" do
58
- optional :wxid, :string, 1
59
- optional :name, :string, 2
60
- optional :remark, :string, 3
61
- optional :contact_type, :int32, 4
62
- end
63
-
64
- # 联系人列表
65
- add_message "ContactList" do
66
- repeated :contacts, :message, 1, "Contact"
67
- end
68
-
69
- # 文本消息
70
- add_message "TextMessage" do
71
- optional :receiver, :string, 1
72
- optional :content, :string, 2
73
- optional :aters, :string, 3
74
- end
75
- end
76
- end
77
-
78
- # 获取消息类
79
- RpcRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("RpcRequest").msgclass
80
- RpcResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("RpcResponse").msgclass
81
- User = Google::Protobuf::DescriptorPool.generated_pool.lookup("User").msgclass
82
- Contact = Google::Protobuf::DescriptorPool.generated_pool.lookup("Contact").msgclass
83
- ContactList = Google::Protobuf::DescriptorPool.generated_pool.lookup("ContactList").msgclass
84
- TextMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("TextMessage").msgclass
85
-
86
- puts "✅ Protobuf 消息类加载完成"
87
- puts
88
-
89
- # ============================================================================
90
- # 2. 示例 1: 嵌套消息 - 获取联系人列表
91
- # ============================================================================
92
-
93
- puts "示例 1: 嵌套消息 - 获取联系人列表"
94
- puts "=" * 70
95
- puts
96
-
97
- url1 = "tcp://127.0.0.1:15560"
98
-
99
- # 服务器进程
100
- server1_pid = fork do
101
- server = NNG::Socket.new(:pair1)
102
- server.listen(url1)
103
- puts "[服务器] 监听: #{url1}"
104
-
105
- # 接收 RPC 请求
106
- request_data = server.recv
107
- rpc_request = RpcRequest.decode(request_data)
108
-
109
- puts "[服务器] 收到 RPC 调用:"
110
- puts "[服务器] Function: 0x#{rpc_request.func_code.to_s(16)}"
111
- puts "[服务器] Request ID: #{rpc_request.request_id}"
112
- puts "[服务器] Timestamp: #{Time.at(rpc_request.timestamp)}"
113
-
114
- # 构建联系人列表
115
- contacts = ContactList.new(
116
- contacts: [
117
- Contact.new(wxid: "wxid_001", name: "张三", remark: "老同学", contact_type: 1),
118
- Contact.new(wxid: "wxid_002", name: "李四", remark: "同事", contact_type: 1),
119
- Contact.new(wxid: "chatroom_001", name: "技术交流群", remark: "", contact_type: 2)
120
- ]
121
- )
122
-
123
- puts "[服务器] 构建响应: #{contacts.contacts.size} 个联系人"
124
-
125
- # 编码嵌套消息
126
- contacts_data = ContactList.encode(contacts)
127
-
128
- # 构建 RPC 响应
129
- rpc_response = RpcResponse.new(
130
- status: 0,
131
- data: contacts_data,
132
- error_msg: "",
133
- request_id: rpc_request.request_id
134
- )
135
-
136
- # 发送响应
137
- server.send(RpcResponse.encode(rpc_response))
138
- puts "[服务器] 响应已发送"
139
-
140
- server.close
141
- end
142
-
143
- sleep 0.5
144
-
145
- # 客户端
146
- client1 = NNG::Socket.new(:pair1)
147
- client1.dial(url1)
148
- puts "[客户端] 连接: #{url1}"
149
-
150
- # 构建 RPC 请求
151
- rpc_request = RpcRequest.new(
152
- func_code: 0x12, # FUNC_GET_CONTACTS
153
- data: "",
154
- timestamp: Time.now.to_i,
155
- request_id: "req_#{Time.now.to_i}_001"
156
- )
157
-
158
- puts "[客户端] 发送 RPC 请求:"
159
- puts "[客户端] Function: 0x#{rpc_request.func_code.to_s(16)}"
160
- puts "[客户端] Request ID: #{rpc_request.request_id}"
161
-
162
- # 发送请求
163
- client1.send(RpcRequest.encode(rpc_request))
164
-
165
- # 接收响应
166
- response_data = client1.recv
167
- rpc_response = RpcResponse.decode(response_data)
168
-
169
- puts "[客户端] 收到 RPC 响应:"
170
- puts "[客户端] Status: #{rpc_response.status}"
171
- puts "[客户端] Request ID: #{rpc_response.request_id}"
172
-
173
- if rpc_response.status == 0
174
- # 解析嵌套的联系人列表
175
- contacts = ContactList.decode(rpc_response.data)
176
- puts "[客户端] 解析联系人列表 (#{contacts.contacts.size} 个):"
177
-
178
- contacts.contacts.each_with_index do |contact, i|
179
- puts "[客户端] #{i + 1}. #{contact.name} (#{contact.wxid})"
180
- puts "[客户端] 备注: #{contact.remark}" unless contact.remark.empty?
181
- puts "[客户端] 类型: #{contact.contact_type == 1 ? '好友' : '群聊'}"
182
- end
183
- else
184
- puts "[客户端] 错误: #{rpc_response.error_msg}"
185
- end
186
-
187
- client1.close
188
- Process.wait(server1_pid)
189
-
190
- puts
191
- puts
192
-
193
- # ============================================================================
194
- # 3. 示例 2: 发送文本消息
195
- # ============================================================================
196
-
197
- puts "示例 2: 发送文本消息"
198
- puts "=" * 70
199
- puts
200
-
201
- url2 = "tcp://127.0.0.1:15561"
202
-
203
- # 服务器进程
204
- server2_pid = fork do
205
- server = NNG::Socket.new(:pair1)
206
- server.listen(url2)
207
- puts "[服务器] 监听: #{url2}"
208
-
209
- # 接收 RPC 请求
210
- request_data = server.recv
211
- rpc_request = RpcRequest.decode(request_data)
212
-
213
- puts "[服务器] 收到 RPC 调用:"
214
- puts "[服务器] Function: 0x#{rpc_request.func_code.to_s(16)}"
215
-
216
- # 解析文本消息参数
217
- text_msg = TextMessage.decode(rpc_request.data)
218
- puts "[服务器] 解析文本消息:"
219
- puts "[服务器] 接收者: #{text_msg.receiver}"
220
- puts "[服务器] 内容: #{text_msg.content}"
221
- puts "[服务器] @的人: #{text_msg.aters}" unless text_msg.aters.empty?
222
-
223
- # 模拟发送消息
224
- puts "[服务器] 发送消息..."
225
- sleep 0.1
226
- puts "[服务器] 消息发送成功"
227
-
228
- # 构建响应
229
- rpc_response = RpcResponse.new(
230
- status: 0,
231
- data: [1].pack('C'), # 返回 1 表示成功
232
- error_msg: "",
233
- request_id: rpc_request.request_id
234
- )
235
-
236
- server.send(RpcResponse.encode(rpc_response))
237
- server.close
238
- end
239
-
240
- sleep 0.5
241
-
242
- # 客户端
243
- client2 = NNG::Socket.new(:pair1)
244
- client2.dial(url2)
245
- puts "[客户端] 连接: #{url2}"
246
-
247
- # 构建文本消息
248
- text_msg = TextMessage.new(
249
- receiver: "wxid_001",
250
- content: "Hello from NNG + Protobuf!",
251
- aters: ""
252
- )
253
-
254
- # 编码为字节
255
- text_msg_data = TextMessage.encode(text_msg)
256
-
257
- # 构建 RPC 请求
258
- rpc_request = RpcRequest.new(
259
- func_code: 0x20, # FUNC_SEND_TXT
260
- data: text_msg_data,
261
- timestamp: Time.now.to_i,
262
- request_id: "req_#{Time.now.to_i}_002"
263
- )
264
-
265
- puts "[客户端] 发送文本消息:"
266
- puts "[客户端] 接收者: #{text_msg.receiver}"
267
- puts "[客户端] 内容: #{text_msg.content}"
268
-
269
- # 发送请求
270
- client2.send(RpcRequest.encode(rpc_request))
271
-
272
- # 接收响应
273
- response_data = client2.recv
274
- rpc_response = RpcResponse.decode(response_data)
275
-
276
- puts "[客户端] 收到响应:"
277
- if rpc_response.status == 0
278
- puts "[客户端] ✅ 消息发送成功"
279
- else
280
- puts "[客户端] ❌ 发送失败: #{rpc_response.error_msg}"
281
- end
282
-
283
- client2.close
284
- Process.wait(server2_pid)
285
-
286
- puts
287
- puts
288
-
289
- # ============================================================================
290
- # 总结
291
- # ============================================================================
292
-
293
- puts "=" * 70
294
- puts "✅ 示例完成"
295
- puts "=" * 70
296
- puts
297
- puts "关键技术点:"
298
- puts
299
- puts "1. 消息嵌套:"
300
- puts " RpcRequest { data: ContactList { contacts: [Contact, ...] } }"
301
- puts
302
- puts "2. 序列化链:"
303
- puts " 内层: ContactList.encode(contacts) → bytes"
304
- puts " 外层: RpcRequest.encode(request) → bytes"
305
- puts
306
- puts "3. 反序列化链:"
307
- puts " 外层: RpcRequest.decode(bytes) → request"
308
- puts " 内层: ContactList.decode(request.data) → contacts"
309
- puts
310
- puts "4. 实际应用场景:"
311
- puts " • RPC 框架 (如本例)"
312
- puts " • 微服务通信"
313
- puts " • 消息队列"
314
- puts " • 分布式系统数据交换"
315
- puts
316
- puts "5. 优势:"
317
- puts " ✅ 强类型约束"
318
- puts " ✅ 自动编解码"
319
- puts " ✅ 跨语言兼容"
320
- puts " ✅ 高效序列化"
321
- puts " ✅ 版本向后兼容"
322
- puts
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # NNG + Protocol Buffers 高级示例
5
+ # 使用 .proto 文件和复杂的消息嵌套
6
+
7
+ require 'nng'
8
+ require 'google/protobuf'
9
+
10
+ puts "=" * 70
11
+ puts "NNG + Protocol Buffers 高级示例"
12
+ puts "使用 .proto 文件和消息嵌套"
13
+ puts "=" * 70
14
+ puts
15
+
16
+ # ============================================================================
17
+ # 1. 从 .proto 文件生成 Ruby 代码 (编译时)
18
+ # ============================================================================
19
+
20
+ puts "说明: 使用 .proto 文件"
21
+ puts "-" * 70
22
+ puts
23
+ puts "实际项目中应该使用 protoc 编译 .proto 文件:"
24
+ puts " $ protoc --ruby_out=. proto/message.proto"
25
+ puts
26
+ puts "本示例直接在 Ruby 中定义消息 (等效于编译后的代码)"
27
+ puts
28
+
29
+ # 定义消息 (等效于从 message.proto 编译生成)
30
+ Google::Protobuf::DescriptorPool.generated_pool.build do
31
+ add_file("message.proto", syntax: :proto3) do
32
+ # RPC 请求
33
+ add_message "RpcRequest" do
34
+ optional :func_code, :int32, 1
35
+ optional :data, :bytes, 2
36
+ optional :timestamp, :int64, 3
37
+ optional :request_id, :string, 4
38
+ end
39
+
40
+ # RPC 响应
41
+ add_message "RpcResponse" do
42
+ optional :status, :int32, 1
43
+ optional :data, :bytes, 2
44
+ optional :error_msg, :string, 3
45
+ optional :request_id, :string, 4
46
+ end
47
+
48
+ # 用户
49
+ add_message "User" do
50
+ optional :id, :int32, 1
51
+ optional :name, :string, 2
52
+ optional :email, :string, 3
53
+ repeated :tags, :string, 4
54
+ end
55
+
56
+ # 联系人
57
+ add_message "Contact" do
58
+ optional :wxid, :string, 1
59
+ optional :name, :string, 2
60
+ optional :remark, :string, 3
61
+ optional :contact_type, :int32, 4
62
+ end
63
+
64
+ # 联系人列表
65
+ add_message "ContactList" do
66
+ repeated :contacts, :message, 1, "Contact"
67
+ end
68
+
69
+ # 文本消息
70
+ add_message "TextMessage" do
71
+ optional :receiver, :string, 1
72
+ optional :content, :string, 2
73
+ optional :aters, :string, 3
74
+ end
75
+ end
76
+ end
77
+
78
+ # 获取消息类
79
+ RpcRequest = Google::Protobuf::DescriptorPool.generated_pool.lookup("RpcRequest").msgclass
80
+ RpcResponse = Google::Protobuf::DescriptorPool.generated_pool.lookup("RpcResponse").msgclass
81
+ User = Google::Protobuf::DescriptorPool.generated_pool.lookup("User").msgclass
82
+ Contact = Google::Protobuf::DescriptorPool.generated_pool.lookup("Contact").msgclass
83
+ ContactList = Google::Protobuf::DescriptorPool.generated_pool.lookup("ContactList").msgclass
84
+ TextMessage = Google::Protobuf::DescriptorPool.generated_pool.lookup("TextMessage").msgclass
85
+
86
+ puts "✅ Protobuf 消息类加载完成"
87
+ puts
88
+
89
+ # ============================================================================
90
+ # 2. 示例 1: 嵌套消息 - 获取联系人列表
91
+ # ============================================================================
92
+
93
+ puts "示例 1: 嵌套消息 - 获取联系人列表"
94
+ puts "=" * 70
95
+ puts
96
+
97
+ url1 = "tcp://127.0.0.1:15560"
98
+
99
+ # 服务器进程
100
+ server1_pid = fork do
101
+ server = NNG::Socket.new(:pair1)
102
+ server.listen(url1)
103
+ puts "[服务器] 监听: #{url1}"
104
+
105
+ # 接收 RPC 请求
106
+ request_data = server.recv
107
+ rpc_request = RpcRequest.decode(request_data)
108
+
109
+ puts "[服务器] 收到 RPC 调用:"
110
+ puts "[服务器] Function: 0x#{rpc_request.func_code.to_s(16)}"
111
+ puts "[服务器] Request ID: #{rpc_request.request_id}"
112
+ puts "[服务器] Timestamp: #{Time.at(rpc_request.timestamp)}"
113
+
114
+ # 构建联系人列表
115
+ contacts = ContactList.new(
116
+ contacts: [
117
+ Contact.new(wxid: "wxid_001", name: "张三", remark: "老同学", contact_type: 1),
118
+ Contact.new(wxid: "wxid_002", name: "李四", remark: "同事", contact_type: 1),
119
+ Contact.new(wxid: "chatroom_001", name: "技术交流群", remark: "", contact_type: 2)
120
+ ]
121
+ )
122
+
123
+ puts "[服务器] 构建响应: #{contacts.contacts.size} 个联系人"
124
+
125
+ # 编码嵌套消息
126
+ contacts_data = ContactList.encode(contacts)
127
+
128
+ # 构建 RPC 响应
129
+ rpc_response = RpcResponse.new(
130
+ status: 0,
131
+ data: contacts_data,
132
+ error_msg: "",
133
+ request_id: rpc_request.request_id
134
+ )
135
+
136
+ # 发送响应
137
+ server.send(RpcResponse.encode(rpc_response))
138
+ puts "[服务器] 响应已发送"
139
+
140
+ server.close
141
+ end
142
+
143
+ sleep 0.5
144
+
145
+ # 客户端
146
+ client1 = NNG::Socket.new(:pair1)
147
+ client1.dial(url1)
148
+ puts "[客户端] 连接: #{url1}"
149
+
150
+ # 构建 RPC 请求
151
+ rpc_request = RpcRequest.new(
152
+ func_code: 0x12, # FUNC_GET_CONTACTS
153
+ data: "",
154
+ timestamp: Time.now.to_i,
155
+ request_id: "req_#{Time.now.to_i}_001"
156
+ )
157
+
158
+ puts "[客户端] 发送 RPC 请求:"
159
+ puts "[客户端] Function: 0x#{rpc_request.func_code.to_s(16)}"
160
+ puts "[客户端] Request ID: #{rpc_request.request_id}"
161
+
162
+ # 发送请求
163
+ client1.send(RpcRequest.encode(rpc_request))
164
+
165
+ # 接收响应
166
+ response_data = client1.recv
167
+ rpc_response = RpcResponse.decode(response_data)
168
+
169
+ puts "[客户端] 收到 RPC 响应:"
170
+ puts "[客户端] Status: #{rpc_response.status}"
171
+ puts "[客户端] Request ID: #{rpc_response.request_id}"
172
+
173
+ if rpc_response.status == 0
174
+ # 解析嵌套的联系人列表
175
+ contacts = ContactList.decode(rpc_response.data)
176
+ puts "[客户端] 解析联系人列表 (#{contacts.contacts.size} 个):"
177
+
178
+ contacts.contacts.each_with_index do |contact, i|
179
+ puts "[客户端] #{i + 1}. #{contact.name} (#{contact.wxid})"
180
+ puts "[客户端] 备注: #{contact.remark}" unless contact.remark.empty?
181
+ puts "[客户端] 类型: #{contact.contact_type == 1 ? '好友' : '群聊'}"
182
+ end
183
+ else
184
+ puts "[客户端] 错误: #{rpc_response.error_msg}"
185
+ end
186
+
187
+ client1.close
188
+ Process.wait(server1_pid)
189
+
190
+ puts
191
+ puts
192
+
193
+ # ============================================================================
194
+ # 3. 示例 2: 发送文本消息
195
+ # ============================================================================
196
+
197
+ puts "示例 2: 发送文本消息"
198
+ puts "=" * 70
199
+ puts
200
+
201
+ url2 = "tcp://127.0.0.1:15561"
202
+
203
+ # 服务器进程
204
+ server2_pid = fork do
205
+ server = NNG::Socket.new(:pair1)
206
+ server.listen(url2)
207
+ puts "[服务器] 监听: #{url2}"
208
+
209
+ # 接收 RPC 请求
210
+ request_data = server.recv
211
+ rpc_request = RpcRequest.decode(request_data)
212
+
213
+ puts "[服务器] 收到 RPC 调用:"
214
+ puts "[服务器] Function: 0x#{rpc_request.func_code.to_s(16)}"
215
+
216
+ # 解析文本消息参数
217
+ text_msg = TextMessage.decode(rpc_request.data)
218
+ puts "[服务器] 解析文本消息:"
219
+ puts "[服务器] 接收者: #{text_msg.receiver}"
220
+ puts "[服务器] 内容: #{text_msg.content}"
221
+ puts "[服务器] @的人: #{text_msg.aters}" unless text_msg.aters.empty?
222
+
223
+ # 模拟发送消息
224
+ puts "[服务器] 发送消息..."
225
+ sleep 0.1
226
+ puts "[服务器] 消息发送成功"
227
+
228
+ # 构建响应
229
+ rpc_response = RpcResponse.new(
230
+ status: 0,
231
+ data: [1].pack('C'), # 返回 1 表示成功
232
+ error_msg: "",
233
+ request_id: rpc_request.request_id
234
+ )
235
+
236
+ server.send(RpcResponse.encode(rpc_response))
237
+ server.close
238
+ end
239
+
240
+ sleep 0.5
241
+
242
+ # 客户端
243
+ client2 = NNG::Socket.new(:pair1)
244
+ client2.dial(url2)
245
+ puts "[客户端] 连接: #{url2}"
246
+
247
+ # 构建文本消息
248
+ text_msg = TextMessage.new(
249
+ receiver: "wxid_001",
250
+ content: "Hello from NNG + Protobuf!",
251
+ aters: ""
252
+ )
253
+
254
+ # 编码为字节
255
+ text_msg_data = TextMessage.encode(text_msg)
256
+
257
+ # 构建 RPC 请求
258
+ rpc_request = RpcRequest.new(
259
+ func_code: 0x20, # FUNC_SEND_TXT
260
+ data: text_msg_data,
261
+ timestamp: Time.now.to_i,
262
+ request_id: "req_#{Time.now.to_i}_002"
263
+ )
264
+
265
+ puts "[客户端] 发送文本消息:"
266
+ puts "[客户端] 接收者: #{text_msg.receiver}"
267
+ puts "[客户端] 内容: #{text_msg.content}"
268
+
269
+ # 发送请求
270
+ client2.send(RpcRequest.encode(rpc_request))
271
+
272
+ # 接收响应
273
+ response_data = client2.recv
274
+ rpc_response = RpcResponse.decode(response_data)
275
+
276
+ puts "[客户端] 收到响应:"
277
+ if rpc_response.status == 0
278
+ puts "[客户端] ✅ 消息发送成功"
279
+ else
280
+ puts "[客户端] ❌ 发送失败: #{rpc_response.error_msg}"
281
+ end
282
+
283
+ client2.close
284
+ Process.wait(server2_pid)
285
+
286
+ puts
287
+ puts
288
+
289
+ # ============================================================================
290
+ # 总结
291
+ # ============================================================================
292
+
293
+ puts "=" * 70
294
+ puts "✅ 示例完成"
295
+ puts "=" * 70
296
+ puts
297
+ puts "关键技术点:"
298
+ puts
299
+ puts "1. 消息嵌套:"
300
+ puts " RpcRequest { data: ContactList { contacts: [Contact, ...] } }"
301
+ puts
302
+ puts "2. 序列化链:"
303
+ puts " 内层: ContactList.encode(contacts) → bytes"
304
+ puts " 外层: RpcRequest.encode(request) → bytes"
305
+ puts
306
+ puts "3. 反序列化链:"
307
+ puts " 外层: RpcRequest.decode(bytes) → request"
308
+ puts " 内层: ContactList.decode(request.data) → contacts"
309
+ puts
310
+ puts "4. 实际应用场景:"
311
+ puts " • RPC 框架 (如本例)"
312
+ puts " • 微服务通信"
313
+ puts " • 消息队列"
314
+ puts " • 分布式系统数据交换"
315
+ puts
316
+ puts "5. 优势:"
317
+ puts " ✅ 强类型约束"
318
+ puts " ✅ 自动编解码"
319
+ puts " ✅ 跨语言兼容"
320
+ puts " ✅ 高效序列化"
321
+ puts " ✅ 版本向后兼容"
322
+ puts