如何创建可在Rust多线程服务器中使用的结构?

时间:2016-07-01 01:30:59

标签: multithreading concurrency server rust automatic-ref-counting

我想实现一个简单的服务器,由我项目的3个不同模块使用 这些模块将数据发送到服务器,服务器将其保存到文件中,并在这些模块完成工作时合并这些信息。 所有这些信息都有时间戳(浮点数)和标签(浮点数或字符串)。

这是我保存这些信息的数据结构:

pub struct Data {
    file_name: String,
    logs: Vec<(f32, String)>,
    measures: Vec<(f32, f32)>,
    statements: Vec<(f32, String)>,
}

我使用socket与服务器进行交互。

我还使用Arc来实现Data结构,并使其可以为每个模块共享。
因此,当我处理客户端时,我验证模块发送的消息是否正确,如果是,我调用一个新函数来处理并将消息保存在良好的数据结构字段中logs,{{ 1}}或measures)。

statements

我在// Current ip address let ip_addr: &str = &format!("{}:{}", &ip, port); // Bind the current IP address let listener = match TcpListener::bind(ip_addr) { Ok(listener) => listener, Err(error) => panic!("Canno't bind {}, due to error {}", ip_addr, error), }; let global_data_struct = Data::new(DEFAULT_FILE.to_string()); let global_data_struct_shared = Arc::new(global_data_struct); // Get and process streams for stream in listener.incoming() { let mut global_data_struct_shared_clone = global_data_struct_shared.clone(); thread::spawn(move || { // Borrow stream let stream = stream; match stream { // Get the stream value Ok(mut stream_v) => { let current_ip = stream_v.peer_addr().unwrap().ip(); let current_port = stream_v.peer_addr().unwrap().port(); println!("Connected with peer {}:{}", current_ip, current_port); // PROBLEM IN handle_client! // A get_mut from global_data_struct_shared_clone // returns to me None, not a value - so I // can't access to global_data_struct_shared_clone // fields :'( handle_client(&mut stream_v, &mut global_data_struct_shared_clone); }, Err(_) => error!("Canno't decode stream"), } }); } // Stop listening drop(listener); 中获取可变引用以处理handle_client中的字段时遇到一些问题,因为global_data_struct_shared_clone返回给我Arc::get_mut(global_data_struct_shared_clone) - 由于{{1}每个传入的请求。

有人可以帮我正确管理这3个模块之间的这种结构吗?

1 个答案:

答案 0 :(得分:0)

Rust的见解是通过强制执行别名XOR可变性来实现内存安全。

实施这一单一原则可以防止整个类别的错误:指针/迭代器失效(这是目标)以及数据竞争

Rust会尽可能地在编译时尝试强制执行此原则;但是,如果用户通过使用专用类型/方法选择,它也可以在运行时强制执行它。

Arc::get_mut就是这样一种方法。 Arc(原子参考计数指针)专门用于在多个所有者之间共享引用,这意味着别名,因此默认情况下不允许可变性; Arc::get_mut将执行运行时检查:如果指针实际上不是别名(计数为1),则它允许可变性。

但是,正如您所知,这不适合您的情况,因为Arc在该时间点存在别名。

所以你需要转向其他类型。

最简单的解决方案是Arc<Mutex<...>>Arc允许共享,Mutex允许受控制的可变性,您可以与Mutex强制执行的运行时控制可变性共享。< / p>

这是粗粒度的,但可能就足够了。

更复杂的方法可以使用RwLock(读者 - 写作者锁定),更细粒度的Mutex甚至原子;但我会建议从一个Mutex开始,看看它是怎么回事,你必须在跑步前走路。