Rust + mio tcp 客户端:连接类型需要明确的生命周期

Rust + mio tcp client: explicit lifetime required in the type of connection

我想用mio实现tcp客户端。这是我的代码:

pub struct Client<'a> {
    pub connected: bool,
    connection: Option<&'a TcpStream>,
    auth_handler: auth::AuthHandler<'a>,
}

impl Client<'_> {
    pub fn connect(&mut self, host: &str, port: i16) {
        let addr_list = format!("{}:{}", host, port)
            .to_socket_addrs()
            .unwrap();

        let addr = addr_list.last().unwrap();

        match TcpStream::connect(addr) {
            Ok(stream) => {
                self.connected = true;
                self.connection = Some(&stream);
                self.auth_handler.init(self.connection.unwrap());
                self.auth_handler.authenticate("login".to_string(), "password".to_string());
                println!("Connected to {}:{}", host, port);
            }
            Err(..) => {
                println!("Cannot connect !");
            }
        }
    }

    pub fn listen(&mut self) {
        let mut connection = self.connection.as_mut().unwrap();
        let mut poll = Poll::new().unwrap();
        let mut events = Events::with_capacity(256);

        poll.registry().register(
            connection,
            CLIENT,
            Interest::READABLE | Interest::WRITABLE
        );

        loop {
            poll.poll(&mut events, None).unwrap();

            for event in events.iter() {
                match event.token() {
                    CLIENT => {
                        if event.is_writable() {
                            // ...
                        }

                        if event.is_readable() {
                            println!("Data")
                        }
                    },
                    _ => (),
                }
            }
        }
    }

    pub fn new<'a>() -> Client<'a> {
        Client {
            connected: false,
            connection: None,
            auth_handler: auth::AuthHandler {
                connection: None::<&'a TcpStream>,
            },
        }
    }
}

以及我的授权处理程序代码:

pub struct AuthHandler<'a> {
    pub connection: Option<&'a TcpStream>,
}

impl AuthHandler {
    pub fn authenticate(&self, login: String, password: String) {
        // ...
    }

    pub fn new<'a>() -> AuthHandler<'a> {
        AuthHandler {
            connection: None::<&'a TcpStream>,
        }
    }

    pub fn init(&mut self, connection: &TcpStream) {
        self.connection = Some(&connection);  // error here see ERRORS below
    }
}

编译时出现错误“错误[E0621]:连接类型需要明确的生命周期”:

self.connection = Some(&connection);
                  ^^^^^^^^^^^^^^^^^ lifetime `'static` required

如何解决?在我这边,我不确定 static 生命周期是否正常,因为我想在通过身份验证并登录后破坏连接。

connection 的生命周期实际上是 'a,但从您发布的代码来看,没有人拥有 TcpStream。您可以使用 AuthHandlers 生命周期修复您遇到的特定错误:

impl<'a> AuthHandler<'a> {
    pub fn authenticate(&self, login: String, password: String) {
        // ...
    }

    pub fn new() -> AuthHandler {
        AuthHandler {
            connection: None,
        }
    }

    pub fn init(&mut self, connection: &'a TcpStream) {
        self.connection = Some(connection);
    }
}

但我希望您随后会收到其他错误,因为实际上 Client 是一个 self-referential 结构。

因此,共享这些对象之间连接的一种方法是将其放入 Arc<Mutex<TcpStream>> 并在您的两个对象之间共享:

pub struct Client<'a> {
    pub connected: bool,
    connection: Option<Arc<Mutex<TcpStream>>>,
    auth_handler: auth::AuthHandler<'a>,
}

pub struct AuthHandler {
    pub connection: Option<Arc<Mutex<TcpStream>>>,
}

那么 TcpStream 只要你需要它就会一直存在。当然,您需要在每次使用时 .lock() 它。

另一种选择是仅在使用 TcpStream 时将其传递给 AuthHandler

pub struct AuthHandler;

impl AuthHandler {
    pub fn authenticate(&self, login: String, password: String, stream: &TcpStream) {
        // ...
    }
}