簡體   English   中英

如何創建可以在 Rust 多線程服務器中使用的結構?

[英]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結構,並使其可用於這些模塊中的每一個。
因此,當我處理客戶端時,我會驗證模塊發送的消息是否正確,如果是,則調用一個新函數來處理並將消息保存在良好的數據結構字段( logsmeasuresstatements )中。

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM