【问题标题】:How to fix "moved value" problem with a TcpStream? [duplicate]如何解决 TcpStream 的“移动值”问题? [复制]
【发布时间】:2019-11-19 00:00:32
【问题描述】:

我正在尝试将数据包/字节从 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)
    }
}

【问题讨论】:

  • 您能添加transfer_server_client_packettransfer_client_server_packet 签名吗?发生了什么已经很清楚了(简而言之,如果他们不需要,他们不应该接受self),但这应该为我们和未来的读者简化事情。
  • 将您的连接包装成Arc&lt;&gt;。这将解决moved value 问题。然而,您的方法签名可能包含&amp;mut self,这将导致一个新问题,因为单独的Arc 不允许被可变借用。然后,您应该考虑一个具有内部可变性的解决方案。首先添加@Cerberus 提到的签名。

标签: rust


【解决方案1】:

一旦你移动了一个值——在本例中是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();
});

此设置管理共享资源,因此一次只有一个线程可以对其进行变异。它还将确保在两个线程都完成后丢弃资源。


话虽如此,我会考虑重构您的代码:两个线程实际上不需要相同的TcpStreams。共享成为必要的唯一原因是您将两个流存储在同一个结构中,这意味着您不能在不借另一个的情况下借用一个。

【讨论】:

    猜你喜欢
    • 2021-03-10
    • 1970-01-01
    • 2021-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 2020-06-12
    • 1970-01-01
    相关资源
    最近更新 更多