0

我想使用 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生命周期是否可以,因为我想在经过身份验证和登录后破坏连接。

4

1 回答 1

1

的生命周期connection确实是'a,但是从您发布的代码来看,没有人拥有TcpStream. AuthHandler您可以通过使用s 生命周期来修复您遇到的特定错误:

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是一个自引用结构。

因此,在这些对象之间共享连接的一种方法是将其放在 aArc<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()无论何时使用它都需要它。

另一种选择是仅在使用时传递TcpStreamto :AuthHandler

pub struct AuthHandler;

impl AuthHandler {
    pub fn authenticate(&self, login: String, password: String, stream: &TcpStream) {
        // ...
    }
}
于 2022-01-27T17:40:07.370 回答