我正在编写一个简单的聊天服务器,它向所有连接的客户端广播消息。
由于我是初学者,代码可能看起来很糟糕。对等点尚未在任何地方使用,因为我想将其传递给handle_client
函数也是如此,因此当数据在流中可用并成功读取时,我想在所有连接的客户端上广播它。我知道这不是一个好方法,我只是想了解一般情况下我该如何做这样的事情。
use std::io::BufRead;
use std::io::Write;
use std::net::{TcpListener, TcpStream};
use std::sync::Arc;
fn handle_client(arc: Arc<TcpStream>) -> std::io::Result<()> {
let mut stream = Arc::try_unwrap(arc).unwrap();
stream.write(b"Welcome to the server!\r\n")?;
println!("incomming connection: {:?}", stream);
std::thread::spawn(move || -> std::io::Result<()> {
let peer_addr = stream.peer_addr()?;
let mut reader = std::io::BufReader::new(stream);
let mut buf = String::new();
loop {
let bytes_read = reader.read_line(&mut buf)?;
if bytes_read == 0 {
println!("client disconnected {}", peer_addr);
return Ok(());
}
buf.remove(bytes_read - 1);
println!("{}: {}", peer_addr, buf);
buf.clear();
}
});
Ok(())
}
fn start() -> std::io::Result<()> {
let listener = TcpListener::bind("0.0.0.0:1111")?;
println!("listening on {}", listener.local_addr()?.port());
let mut peers: Vec<Arc<TcpStream>> = vec![];
for stream in listener.incoming() {
let mut stream = stream.unwrap();
let arc = Arc::new(stream);
peers.push(arc.clone());
handle_client(arc.clone()).unwrap();
}
Ok(())
}
fn main() -> std::io::Result<()> {
start()
}
它编译得很好,但是let mut stream = Arc::try_unwrap(arc).unwrap();
in the handle_client
函数恐慌。我究竟做错了什么?为什么会惊慌呢?
为什么会惊慌呢?
你正在呼唤unwrap
on a Result::Err
. The Err
来自try_unwrap
失败于Arc
.
我究竟做错了什么?
拆开一个Arc
will move它的价值并拥有它。这会失败,因为存在相同的三个克隆Arc
:
- 主循环中的一个仍在范围内
- 一个在
peers
vector
- 你试图打开里面的那个
handle_client
.
如果 Rust 允许您解开并移动该值,那么其他两个克隆将变得无效。
您可以使用而不是解开该值Arc
's Deref
借用它的实现:
let stream: &TcpStream = &arc;
由于您现在正在借用价值Arc
,您需要移动范围arc
新线程中的变量,否则借用检查器将无法确保它与线程一样长:
fn handle_client(arc: Arc<TcpStream>) -> std::io::Result<()> {
std::thread::spawn(move || -> std::io::Result<()> {
let mut stream: &TcpStream = &arc;
stream.write(b"Welcome to the server!\r\n")?;
let peer_addr = stream.peer_addr()?;
let mut reader = std::io::BufReader::new(stream);
let mut buf = String::new();
// ...
}
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)