baoshiwei
6 天以前 5bf14aed888cd0e258e325c65f14022dad02985b
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
use tokio::net::windows::named_pipe::{ServerOptions};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
use rand::Rng;
 
// 生成模拟的六轴力数据
fn generate_force_data() -> String {
    let mut rng = rand::thread_rng();
    let force_data = [
        rng.gen_range(-100.0..100.0), // Fx
        rng.gen_range(-100.0..100.0), // Fy
        rng.gen_range(-100.0..100.0), // Fz
        rng.gen_range(-10.0..10.0),   // Mx
        rng.gen_range(-10.0..10.0),   // My
        rng.gen_range(-10.0..10.0),   // Mz
    ];
    
    serde_json::to_string(&force_data).unwrap_or_else(|_| "[0,0,0,0,0,0]".to_string())
}
 
// 处理客户端请求
fn process_request(request: &str) -> String {
    match request {
        "GET_FORCE_DATA" => generate_force_data(),
        _ => request.to_string(), // 对于其他请求,简单地回显
    }
}
 
pub async fn start_pipe_server(pipe_name: &str) -> Result<(), Box<dyn std::error::Error>> {
    let full_pipe_name = format!(r"\\.\pipe\{}", pipe_name);
    let pipe_name_clone = pipe_name.to_string();
    
    // 在单独的线程中运行管道服务器,这样函数可以立即返回
    tokio::spawn(async move {
        loop {
            // 每次循环创建新的管道实例,确保之前的连接已完全关闭
            let server = match ServerOptions::new()
                .first_pipe_instance(false) // 允许多个实例,避免错误231
                .create(&full_pipe_name) {
                    Ok(s) => s,
                    Err(e) => {
                        eprintln!("Error creating pipe server: {}", e);
                        // 如果创建失败,等待一段时间后重试
                        tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
                        continue;
                    }
                };
 
            println!("Pipe server listening on {}", full_pipe_name);
            
            // 等待客户端连接
            if let Err(e) = server.connect().await {
                eprintln!("Error connecting to pipe: {}", e);
                // 连接失败后等待一段时间再重试
                tokio::time::sleep(tokio::time::Duration::from_secs(1)).await;
                continue;
            }
            
            // 处理客户端请求
            let mut buf = [0u8; 1024];
            let mut server = server; // 移动所有权到当前作用域
            
            loop {
                // 读取客户端请求
                let n = match server.read(&mut buf).await {
                    Ok(n) => n,
                    Err(e) => {
                        eprintln!("Error reading from pipe: {}", e);
                        break; // 读取错误,退出内层循环,创建新的管道实例
                    }
                };
                
                if n == 0 { break; } // 客户端断开连接
                
                let msg = String::from_utf8_lossy(&buf[..n]);
                println!("Received: {}", msg);
                
                // 处理请求并返回响应
                let response = process_request(&msg);
                
                if let Err(e) = server.write_all(response.as_bytes()).await {
                    eprintln!("Error writing to pipe: {}", e);
                    break; // 写入错误,退出内层循环,创建新的管道实例
                }
            }
            
            // 客户端断开连接后,显式关闭当前管道实例
            // 这里server会在作用域结束时自动关闭,但我们可以添加日志
            println!("Client disconnected, creating new pipe instance");
            // 短暂延迟,确保资源完全释放
            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;
        }
    });
    
    // 立即返回,不阻塞调用者
    println!("Pipe server started for {}", pipe_name_clone);
    Ok(())
}