为什么Arc :: try_unwrap()引起恐慌? [英] Why does Arc::try_unwrap() cause a panic?

查看:68
本文介绍了为什么Arc :: try_unwrap()引起恐慌?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个简单的聊天服务器,该服务器将消息广播到所有连接的客户端.

I'm writing a simple chat server which broadcasts messages to all the clients connected.

由于我是初学者,因此代码看起来可能很糟糕.对等体尚未在任何地方使用,因为我也想将其传递给handle_client函数,因此当数据在流中可用并成功读取时,我想在所有连接的客户端上广播它.我知道这不是一个好方法,我只是想了解我一般如何做这样的事情.

The code might look terrible, since I'm a beginner. Peers are not used anywhere yet, since I want to pass it to handle_client function as well, so when data will be available in stream and read successfully, I want to broadcast it over all the clients connected. I understand this is not a good approach, I'm just trying to understand how can I do things like this in general.

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()
}

它可以正常编译,但是handle_client函数中的let mut stream = Arc::try_unwrap(arc).unwrap();会出现混乱.我究竟做错了什么?为什么会惊慌?

It compiles fine, but let mut stream = Arc::try_unwrap(arc).unwrap(); in the handle_client function panics. What am I doing wrong? Why is it panicking?

推荐答案

为什么会惊慌?

Why is it panicking?

您在Result::Err上呼叫unwrap. Err来自try_unwrap,而Arc失败.

You are calling unwrap on a Result::Err. The Err comes from try_unwrap failing on the Arc.

我在做什么错了?

What am I doing wrong?

展开Arc的包装将移动其值并获得其所有权.之所以失败,是因为存在三个相同Arc的克隆:

Unwrapping an Arc will move its value and take ownership of it. This fails because there are three clones of the same Arc:

  • 主循环中仍在作用域中的一个
  • peers向量中的一个
  • 您要在handle_client内部展开的那个.
  • one in the main loop which is still in scope
  • one in the peers vector
  • the one that you are trying to unwrap inside handle_client.

如果Rust允许您解开并移动该值,则其他两个克隆将变得无效. 您可以使用ArcDeref实现来借用该值,而不用解开该值:

The other two clones would become invalid if Rust allowed you to unwrap and move the value. Instead of unwrapping the value you can use Arc's Deref implementation to borrow it:

let stream: &TcpStream = &arc;

由于您现在要从Arc借用值,因此需要在新线程内移动arc变量的作用域,否则借用检查器将无法确保其生存期达到线程:

Since you are now borrowing the value from the Arc, you need to move the scope of the arc variable inside the new thread, otherwise the borrow checker won't be able to ensure that it lives as long as the thread:

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();

        // ... 
     }
}

这篇关于为什么Arc :: try_unwrap()引起恐慌?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆