我正在尝试创建对当前 TCP 连接的引用。在此代码中,我尝试在循环中打印当前 TCP 连接的对等地址并休眠 10 秒,我遇到的错误是访问多个线程之间的数据。
我希望能够在任何给定时间点从不同的线程操作 TCPStream,以执行诸如关闭 TCPStream 或获取对等地址之类的操作。
您能否让我知道我做错了什么,以便我可以更好地了解 Arc 和 Mutex 的工作原理?
use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::Duration;
fn main() {
let server = Server {
connected_clients: Arc::new(Mutex::new(Vec::new()))
};
thread::spawn(move || {
let listener = TcpListener::bind("127.0.0.1:25565").unwrap();
// For each new connection start a new thread
for stream in listener.incoming() {
let stream = Arc::new(Mutex::new(stream.unwrap()));
let client = Client {
stream: stream.clone()
};
let cc = server.connected_clients.clone();
cc.lock().unwrap().push(client);
thread::spawn(move || {
// TODO: Add client to the connected_clients Vec
let mut buffer = [0; 1024];
loop {
stream.lock().unwrap().read(&mut buffer).unwrap();
println!("{}", String::from_utf8(Vec::from(&buffer[..])).unwrap().trim_end_matches(char::from(0)));
}
});
}
});
loop {
thread::sleep(Duration::from_secs(10));
// let vec = server.lock().unwrap().connected_clients.lock().unwrap().iter();
for client in server.connected_clients.lock().unwrap().iter() {
println!("{:?}", client.stream.lock().unwrap().peer_addr().unwrap())
}
}
}
#[derive(Debug)]
struct Server {
connected_clients: Arc<Mutex<Vec<Client>>>,
}
#[derive(Debug)]
struct Client {
stream: Arc<Mutex<TcpStream>>
}
错误:
error[E0382]: borrow of moved value: `server.connected_clients`
--> src\main.rs:40:23
|
12 | thread::spawn(move || {
| ------- value moved into closure here
...
22 | let cc = server.connected_clients.clone();
| ------------------------ variable moved due to use in closure
...
40 | for client in server.connected_clients.lock().unwrap().iter() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value borrowed here after move
|
= note: move occurs because `server.connected_clients` has type `Arc<Mutex<Vec<Client>>>`, which does not implement the `Copy` trait
= note: borrow occurs due to deref coercion to `Mutex<Vec<Client>>`
最佳答案
只需移动该行 let cc = server.connected_clients.clone();
第一行之前 thread::spawn(move || {
.
move
闭包的关键字现在将取得 cc
的所有权,那么原来的server.connected_clients
将在程序结束时保持可用于循环。
背后的想法Rc::clone()
或Arc::clone()
正是为了move
的目的闭包:我们不是将指向资源的原始引用计数指针移动到闭包中,而是将其克隆移动,并且指向资源的原始引用计数指针在其原始上下文中仍然可用。
关于multithreading - Rust:使用互斥体允许从多个线程访问数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73392374/