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

我是否可以维护TCP流的Vec,以便在其中一个线程读取新输入时跨线程写入它们?,tcp,rust,tcpserver,Tcp,Rust,Tcpserver,我想做消息广播:当一个客户端发送消息时,服务器将其写入每个套接字。我的主要问题是我不知道如何将Vec发送到线程。我不能使用Mutex,因为这将锁定其他线程对Vec的访问。我无法克隆和发送,因为无法克隆和发送TcpStream。这是我迄今为止的尝试 use std::net::{TcpStream, TcpListener}; use std::io::prelude::*; use std::sync::{Arc, Mutex}; use std::thread; use std::sync::

我想做消息广播:当一个客户端发送消息时,服务器将其写入每个套接字。我的主要问题是我不知道如何将
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;
        };
    }
}
使用std::net:{TcpStream,TcpListener};
使用std::io::prelude::*;
使用std::sync::{Arc,Mutex};
使用std::线程;
使用std::sync::mpsc::{channel,Receiver};
使用std::cell::RefCell;
类型StreamSet=Arc;
类型=弧形;
fn main(){
让listener=TcpListener::bind(“0.0.0.0:8000”).unwrap();
让mut connection_set:StreamSet=Arc::new(RefCell::new(vec![]);
设mut-id=0;
let(tx,rx)=信道();
设rx=Arc::new(互斥体::new(rx));
对于listener.incoming()中的流{
让receiver=rx.clone();
let stream=stream.unwrap();
(*连接集).follow_mut().push(流);
println!(“与客户端{}建立的连接,id);
线程::生成(移动| |句柄|连接(接收方,id));
id+=1;
tx.send(connection_set.clone()).unwrap();
}
}
fn手柄连接(rx:StreamReceiver,id:usize){
让溪流流淌;
{
streams=*(rx.lock().unwrap().recv().unwrap()).borrow();
}
让mut连接=&streams[id];
环路{
让mut buffer=[0;512];
如果let Err(_)=connection.read(&mut buffer){
打破
};
println!(“请求:{}”,字符串::from_utf8_lossy(&buffer[…]);
如果let Err(41;)=连接.写入(&缓冲区[…]){
打破
};
如果让Err(41;)=connection.flush(){
打破
};
}
}

另一个想法是为每个套接字生成一个“控制器”线程和一个线程。每个线程都拥有套接字,并有一个将数据发送回控制器的通道。控制器将拥有要发送到每个线程的
Vec
。当一个线程接收到数据时,您将其发送给控制器,控制器复制数据并将其发送回每个工作线程。您可以将数据包装在
弧中
以防止不必要的重复,并且您应该提供一个ID以避免将数据回显给原始发件人(如果需要)

这将在单个线程中完全移动所有权,这将避免您遇到的问题

您可能还希望深入研究,这将允许您执行类似的操作,但无需在1-1映射中生成线程

我不能使用互斥锁,因为这会锁定其他线程的访问

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

因为无法克隆
TcpStream


当然可以。

啊,谢谢。实际上我对编码有点陌生,下个月将完成一年。所以,在使用像tokio这样的抽象之前,我尽可能多地自己实现它,所以我了解引擎盖下发生了什么。我将尝试实现controller-worker模型。每个单独的线程都有一个单独的通道,还是使用相同的接收器、发送器对?我希望控制器线程每个工作线程都有一个唯一的通道向它们发送数据,然后每个工作线程都有一个重复使用的通道返回控制器(因为它们是多个生产者、单消费者通道)。总的来说,应该有N+1个频道。啊,好的。有道理。谢谢