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
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
//use group_controller::GroupController;
use Arc;
//use std::{any, ffi::c_void};
//use async_trait::async_trait;
//use serde::Serialize;
use AsyncWriteExt;
use ;
//use dashmap::DashMap;
//use serde_json::Value;
use ;
//use std::cell::RefCell;
//use anyhow::Result;
//use tokio::io::util::AsyncWriteExt;
//use std::{result::Result as stdResult};
//use std::io::Error as stdError;
//use std::sync::Arc;
use Clone;
/*
// **************以下这几项都不能动,关乎数据转换*********************
//设备模块接口
//#[async_trait]
//#[repr(C)] 不能用,用了DashMap没法插入 有#[repr(C)]的结构体不能使用rust复杂类型,它会强制rust结构体进行c布局,
///破坏结构,公共头文件中定义不透明结构体(C 可见),可以跨C边界,隐藏数据。只有rust发送者接受者明白这个指针代表的类型,
/// 可以安全的类型转换。为什么要跨C边界,因为所有操作系统都是c语言开发的,支持c结构数据
#[repr(C)]//结构体中的元素必须符合FFI规则
pub struct GroupControllerHandle;
// pub type StartGroupFn = unsafe fn(&mut GroupController);
///定义动态库跨边界调用函数
pub type StartGroupFn = unsafe fn(*mut GroupControllerHandle);
//pub type CreateModuleFn = unsafe fn() -> *mut dyn DeviceModule;
///Group的共享容器,键值String是Group的名字,Arc<GroupController>是Group的控制及资源接口,便于Group使用
pub type GroupMap = Arc<DashMap<String, Arc<GroupController>>>;//可能被多个组同时访问,因为使用了DashMap可以读写,Arc只是提供指针
//pub type GroupMap = Arc<DashMap<String, Arc<Mutex<GroupController>>>>;//可能被多个组同时访问,因为使用了DashMap可以读写
///Group的控制及资源接口结构体,因为Group拥有其共享指针,可以安全的访问。其元素都符合Send+Sync
#[derive(Clone)]
pub struct GroupController
{
name:String,
group_map: GroupMap,//设备类的集合引用,智能指针,是GroupMap(Arc)的克隆 Arc 也是Send+Sync
node_map: DashMap<String,Arc<(Arc<OwnedReadHalf>,Arc<OwnedWriteHalf>)>>,//同组节点的TcpStream的集合,
//外代码无法访问,是线程安全的,Send +Sync,这时的TcpClient可以读写,与Arc无关
}
impl GroupController {
pub fn new() ->Self{
Self {
name:"group".to_string(),
group_map: Arc::new(DashMap::new()),
node_map: DashMap::new(),
}
}
///设定组名称
pub fn set_group_name(&mut self,name:String)
{
self.name = name;
// println!("setname..{}",&self.name);
}
///得到组的名称
pub fn get_group_name(&self) ->&str
{
//println!("getname..{}",&self.name);
&self.name
}
///设定group集合指针Arc
pub fn set_group_map(&mut self,group_map:GroupMap){ self.group_map=group_map;}
}
*/
//以上几项都不能修改,否则程序转换会失败
/*
///Group异步接口,支持多线程共享和传递
#[async_trait]
pub trait IController: Send + Sync { //为了指针接口是同步的,不能Send+Sync
fn test(&self);
async fn log(&self,msg_class:&str,msg:&str) -> io::Result<()>;
async fn who(&self);
/*
///接收 TcpStream,并将其劈成读写两部分,以元组的方式存入DashMap中,便于多线程全双工读写
pub async fn handle_socket(&self, node_id: String, mut socket: TcpStream);
*/
/// 从节点容器中找到目标节点,并获得读写句柄元组,便于多线程快速读写
/// group是组名,同一类或者统一标准的类的名称,对应不同动态库;node_id是节点的名字或者id
/// 支持寻址,可以找到其它Group的节点,并收发信息
/// 下一步支持到其他程序或者其他网络上的节点的通讯
// fn get_node_tcpclient(&self, group: &str, node_id: &str) -> Option<Arc<(Arc<OwnedReadHalf>,Arc<OwnedWriteHalf>)>>;
//ReadHalf, WriteHalf是原始流的引用,而OwnedReadHalf,OwnedWriteHalf拥有Tcp流的完整所有权,分离后原始TcpStream不再可用
///共享读写,用Arc实现共享读写,将TcpStream劈成读写两部分,便于异步线程同时读写,
/// 减少TcpStream读写的竞争,因为TcpStream是全双工的
fn sharing_stream(stream: TcpStream) -> (Arc<OwnedReadHalf>,Arc<OwnedWriteHalf>);
}
*/
// #[async_trait]
// impl IController for GroupController {
/// 程序测试用,会在终端打印出"controller test......ok",说明调用GroupController的功能正常
pub async
pub async
// }
/*
///接收 TcpStream,并将其劈成读写两部分,以元组的方式存入DashMap中,便于多线程全双工读写
pub async fn handle_socket(&self, node_id: String, mut socket: TcpStream)
{
// println!("rrrrr");
// 使用 Arc 包装 TcpStream 以便安全共享
let message = format!("{}上线!可以收发信息了。\n", node_id);
let gg= socket.write_all(message.as_bytes()).await;
match gg {
Ok(()) => println!("发送字符成功"),
Err(e) => println!("发送失败{}",e),
}
// println!("成功发送{}字节",3);
let node_id_str=node_id.clone();
// 使用 DashMap 无需显式获取锁
// 使用entry API避免竞争条件
if let Some(old_socket) =
self.node_map.insert(node_id, Arc::new(GroupController::sharing_stream(socket))) {
// 处理被替换的旧socket(如果需要)
drop(old_socket);
eprintln!("Warning: Replaced existing socket for node {}",node_id_str);
}
//println!("ddddddddd");
println!("[Node {} socket stored. Total sockets into_split: {}", self.name,self.node_map.len());
// Ok(())
}
*/
/*
/// 从节点容器中找到目标节点,并获得读写句柄元组,便于多线程快速读写
/// group是组名,同一类或者统一标准的类的名称,对应不同动态库;node_id是节点的名字或者id
/// 支持寻址,可以找到其它Group的节点,并收发信息
/// 下一步支持到其他程序或者其他网络上的节点的通讯
fn get_node_tcpclient(&self, group: &str, node_id: &str) -> Option<Arc<(Arc<OwnedReadHalf>,Arc<OwnedWriteHalf>)>>
{
if group == &self.name {
self.node_map.get(node_id).map(|entry| {
// 克隆Arc,增加引用计数(不复制流本身)
Arc::clone(entry.value())
// entry
// Box::new(entry.value())
// Box::new(**entry.value())
})
}
else {
self.group_map.get(group)
// 从子组中获取节点映射
.and_then(|group_entry: dashmap::mapref::one::Ref<'_, String, Arc<GroupController>>| {
group_entry.value().node_map.get(node_id)
.map(|node_entry|Arc::clone(node_entry.value()))}
)
}
}
*/
// }
//ReadHalf, WriteHalf是原始流的引用,而OwnedReadHalf,OwnedWriteHalf拥有Tcp流的完整所有权,分离后原始TcpStream不再可用
///共享读写,用Arc实现共享读写,将TcpStream劈成读写两部分,便于异步线程同时读写,
/// 减少TcpStream读写的竞争,因为TcpStream是全双工的
// }
/*
///Group异步接口,支持多线程共享和传递
#[async_trait]
pub trait GroupTrait: Send + Sync { //为了指针接口是同步的,不能Send+Sync
fn set_controller_to_group(&mut self, controller: Arc<GroupController>);
fn get_controller_clone(&self) ->Arc<GroupController>;
/// 处理新连接的socket
fn start(controller: Arc<GroupController>);
///async fn send_to_socket(&self)->stdResult<(), stdError>;
async fn handle(&self) ->stdResult<(), stdError>;
async fn test(&self);
// async fn write_data(device_id:String,data_buf:&[u8]) ->stdResult<(), std::io::Error>;
//async fn read_data(device_id: String) -> stdResult<Vec<u8>, std::io::Error>;
}
*/
//全局运行时
// 全局运行时(程序生命周期内只初始化一次),所有的group程序都在这里运行
use OnceLock;
use ;
///全局运行时,所有Group共同使用的
static GLOBAL_RUNTIME: = new;
/// 获取全局运行时句柄
//use std::net::IpAddr; // 使用标准库的IpAddr类型替代String
/// 发送目标结构
/*
/// 注册信息包结构
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Reg {
pub class: String, // 设备类型
pub node: String, // 设备名称或账号
pub version: Option<String>,// 可选的版本信息
pub metadata: Option<String>,// 可选的元数据
}
*/
//*****登记信息*****
use ;
use ;
use RwLock;
use PathBuf;
use Utc;
use Lazy;
/// 全局缓冲区:存储当前使用的文件名和对应的BufWriter<File>
static NOW_BUFWRITER: = new;
/// 辅助函数:获取格式化后的时间
/// 异步日志记录函数
/// group_name:组名,功能类型;msg_class:信息类型;msg:登记信息
async