[英]How do I create a structure that can be used in a Rust multithreaded server?
我想實現一個簡單的服務器,由我的項目的 3 個不同模塊使用。
這些模塊會將數據發送到服務器,服務器會將數據保存到文件中,並在這些模塊完成工作時合並這些信息。 所有這些信息都有時間戳(浮點數)和標簽(浮點數或字符串)。
這是我保存這些信息的數據結構:
pub struct Data {
file_name: String,
logs: Vec<(f32, String)>,
measures: Vec<(f32, f32)>,
statements: Vec<(f32, String)>,
}
我使用socket
與服務器交互。
我還使用Arc
來實現一個Data
結構,並使其可用於這些模塊中的每一個。
因此,當我處理客戶端時,我會驗證模塊發送的消息是否正確,如果是,則調用一個新函數來處理並將消息保存在良好的數據結構字段( logs
、 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)
返回給我None
- 由於每個傳入請求的global_data_struct_shared.clone()
。
有人可以幫我正確管理這 3 個模塊之間的這種結構嗎?
Rust 的見解是通過執行Aliasing XOR Mutability來實現內存安全。
執行這個單一原則可以防止整類錯誤:指針/迭代器失效(這是目標)以及數據競爭。
Rust 會盡可能在編譯時強制執行這個原則; 但是,如果用戶通過使用專用類型/方法選擇加入,它也可以在運行時強制執行。
Arc::get_mut
就是這樣一種方法。 Arc
(原子引用計數指針)專門用於在多個所有者之間共享引用,這意味着別名,因此默認情況下不允許可變性; Arc::get_mut
將執行運行時檢查:如果指針實際上不是別名(計數為 1),則它允許可變性。
但是,正如您所意識到的,這不適合您的情況,因為Arc
在那個時間點是別名的。
所以你需要轉向其他類型。
最簡單的解決方案是Arc<Mutex<...>>
, Arc
允許共享, Mutex
允許受控可變性,您可以與Mutex
強制執行的運行時受控可變性共享。
這是粗粒度的,但可能已經足夠了。
更復雜的方法可以使用RwLock
(讀寫鎖)、更細粒度的Mutex
甚至原子; 但我建議從一個Mutex
,看看它是如何進行的,你必須Mutex
再跑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.