如何解决TcpStream的“移动值”问题?

时间:2019-11-17 22:42:44

标签: rust

我正在尝试将数据包/字节从TcpStream传输到另一个,反之亦然。我创建了一个结构Connection

pub struct Connection {
    pub client_socket: TcpStream,
    pub server_socket: TcpStream
}

我正在尝试打开两个线程,以便可以双向传输所有字节。可悲的是,由于第二次调用连接,我试图使用移动值。我该如何解决?

thread::spawn(move || loop { connection.transfer_server_client_packet(); });
thread::spawn(move || loop { connection.transfer_client_server_packet(); });
impl Connection {
    fn get_packet(&mut self, from_client: bool) -> Result<Packet, io::Error> {
        unimplemented!()
    }
    pub fn get_client_packet(&mut self) -> Result<Packet, io::Error> {
        self.get_packet(true)
    }
    pub fn get_server_packet(&mut self) -> Result<Packet, io::Error> {
        self.get_packet(false)
    }
    fn send_packet(&mut self, from_client: bool, mut packet: Packet) -> Result<Packet, io::Error> {
        unimplemented!()
    }
    pub fn send_client_packet(&mut self, packet: Packet) -> Result<Packet, io::Error> {
        self.send_packet(true, packet)
    }
    pub fn send_server_packet(&mut self, packet: Packet) -> Result<Packet, io::Error> {
        self.send_packet(false, packet)
    }
    fn transfer_packet(&mut self, from_client: bool, to_client: bool) -> Result<usize, io::Error> {
        let packet = if from_client {
            self.get_client_packet()?
        } else {
            self.get_server_packet()?
        };
        if to_client {
            self.send_client_packet(packet)?
        } else {
            self.send_server_packet(packet)?
        };
        Ok(0)
    }
    pub fn transfer_client_server_packet(&mut self) -> Result<usize, io::Error> {
        self.transfer_packet(true, false)
    }
    pub fn transfer_server_client_packet(&mut self) -> Result<usize, io::Error> {
        self.transfer_packet(false, true)
    }
}

1 个答案:

答案 0 :(得分:2)

一旦移动了一个值(在本例中为Connection),您将无法再次使用它。如果需要两个线程来可变地访问同一连接,则可以克隆它或使用同步原语(例如Arc)共享它。

例如:

let connection = Arc::new(Mutex::new(Connection::new()));
let connection_server_client = Arc::clone(&connection);
let connection_client_server = Arc::clone(&connection);

thread::spawn(move || loop {
    let connection = connection_server_client.lock().unwrap();
    connection.transfer_server_client_packet();
});

thread::spawn(move || loop {
    let connection = connection_client_server.lock().unwrap();
    connection.transfer_client_server_packet();
});

此设置管理共享资源,以便一次只能有一个线程对其进行突变。它还将确保在两个线程都使用完资源后将其删除。


话虽如此,我将考虑对您的代码进行重构:两个线程实际上并不需要相同的TcpStream。共享变得必要的唯一原因是,您已将两个流存储在相同的结构中,这意味着您不能借用一个而不同时借用另一个。