我有一台服务器接受来自多个客户端的连接。每个客户端都可以向服务器发送消息,该消息将广播给所有其他客户端。问题是处理每个连接的函数应该具有对服务器的引用。但是,我想在单独的线程中处理连接,所以我不能直接使用引用。
由于scoped
已被弃用,我尝试在self
中包装Arc
,但随后出现了更多问题。以下是我的尝试:
struct Server {
listener: TcpListener,
clients: Vec<TcpStream>
}
impl Server {
fn new() -> Server {
Server {
listener : TcpListener::bind("127.0.0.1:8085").unwrap(),
clients : vec![]
}
}
fn handle(&self) {
println!("test");
}
fn start(mut self) {
let mut handles = vec![];
let a : Arc<Mutex<Server>> = Arc::new(Mutex::new(self));
let mut selfm = a.lock().unwrap();
// cannot borrow as mutable... ?
for stream in selfm.listener.incoming() {
match stream {
Ok(stream) => {
selfm.clients.push(stream);
let aa = a.clone();
handles.push(thread::spawn(move || {
aa.lock().unwrap().handle();
}));
},
Err(e) => { println!("{}", e); },
}
}
}
我不明白该怎么做,我担心所有这些锁都会出现死锁。你有什么建议吗?
答案 0 :(得分:1)
该错误与拥有多个线程几乎无关。正如编译器所说,问题是selfm
已经在行
for stream in selfm.listener.incoming() {
所以它不能在行中可变地借用
selfm.clients.push(stream);
解决此问题的一种方法是在循环之前解构selfm
,因此借用不会发生冲突。您的start
方法将如下所示:
fn start(mut self) {
let mut handles = vec![];
let a : Arc<Mutex<Server>> = Arc::new(Mutex::new(self));
let mut selfm = a.lock().unwrap();
// destructure selfm here to get a reference to the listener and a mutable reference to the clients
let Server { ref listener, ref mut clients} = *selfm;
for stream in listener.incoming() { // listener can be used here
match stream {
Ok(stream) => {
clients.push(stream); // clients can be mutated here
let aa = a.clone();
handles.push(thread::spawn(move || {
aa.lock().unwrap().handle();
}));
},
Err(e) => { println!("{}", e); },
}
}
}
(话虽如此,您关注锁定是正确的,因为互斥锁将保持锁定状态,直到selfm
超出范围,即仅在start
终止时,即从不我会建议一个替代设计,但我不清楚为什么你希望线程能够访问服务器结构。)