代码之家  ›  专栏  ›  技术社区  ›  codeNoob

我可以维护TCP流的Vec,以便在其中一个线程读取新输入时跨线程写入它们吗?

  •  0
  • codeNoob  · 技术社区  · 7 年前

    我想做消息广播:当一个客户机发送消息时,服务器将其写入每个套接字。我的主要问题是我不知道如何发送 Vec Mutex 因为这将锁定其他线程对 Vec公司 用于阅读。我无法克隆并发送,因为 TcpStream 无法克隆和发送。这是我迄今为止的尝试

    use std::net::{TcpStream, TcpListener};
    use std::io::prelude::*;
    use std::sync::{Arc, Mutex};
    use std::thread;
    use std::sync::mpsc::{channel, Receiver};
    use std::cell::RefCell;
    
    type StreamSet = Arc<RefCell<Vec<TcpStream>>>;
    type StreamReceiver = Arc<Mutex<Receiver<StreamSet>>>;
    
    fn main() {
        let listener = TcpListener::bind("0.0.0.0:8000").unwrap();
        let mut connection_set: StreamSet = Arc::new(RefCell::new(vec![]));
        let mut id = 0;
        let (tx, rx) = channel();
        let rx = Arc::new(Mutex::new(rx));
        for stream in listener.incoming() {
            let receiver = rx.clone();
            let stream = stream.unwrap();
            (*connection_set).borrow_mut().push(stream);
            println!("A connection established with client {}", id);
            thread::spawn(move || handle_connection(receiver, id));
            id += 1;
            tx.send(connection_set.clone()).unwrap();
        }
    
    }
    
    fn handle_connection(rx: StreamReceiver, id: usize) {
        let streams;
        {
            streams = *(rx.lock().unwrap().recv().unwrap()).borrow();
        }
        let mut connection = &streams[id];
        loop {
            let mut buffer = [0; 512];
            if let Err(_) = connection.read(&mut buffer) {
                break;
            };
            println!("Request: {}", String::from_utf8_lossy(&buffer[..]));
            if let Err(_) = connection.write(&buffer[..]) {
                break;
            };
            if let Err(_) = connection.flush() {
                break;
            };
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Shepmaster Lukas Kalbertodt    7 年前

    另一个想法是生成一个“控制器”线程 每个插座有一根线。每个线程都拥有套接字,并有一个通道将数据发送回控制器。控制器将拥有一个 Vec 发送到每个线程的通道数。当一个线程接收到数据时,您将其发送给控制器,控制器复制数据并将其发送回每个工作线程。您可以将数据包装在 Arc

    这将所有权完全转移到单个线程中,这应该可以避免您遇到的问题。

    你也可以考虑 Tokio ,这应该允许您执行类似的操作,但不需要在1-1映射中生成线程。

    Mutex 因为这将锁定其他线程的访问

    您可以尝试不同的锁定机制,例如 RwLock

    因为 TcpStream 无法克隆

    TcpStream::try_clone