Первая ошибка говорит о недоступности метода
<anon>:19:16: 19:33 error: no method named `read` found for type `std::io::buffered::BufReader<std::net::tcp::TcpStream>` in the current scope
<anon>:19 reader.read(&mut buffer).unwrap();
^~~~~~~~~~~~~~~~~
и компилятор тут же подсказывает решение:
<anon>:19:16: 19:33 help: items from traits can only be used if the trait is in scope; the following trait is implemented but not in scope, perhaps add a `use` for it:
<anon>:19:16: 19:33 help: candidate #1: use `std::io::Read`
Так что импортируем типаж Read:
use std::io::{self, Read, BufRead, BufReader};
Появляется новая ошибка:
<anon>:19:21: 19:32 error: mismatched types:
expected `&mut [u8]`,
found `&mut collections::string::String`
(expected slice,
found struct `collections::string::String`) [E0308]
<anon>:19 reader.read(&mut buffer).unwrap();
^~~~~~~~~~~
Это потому, что .read
требует &mut [u8]
, а если мы хотим читать сразу в String
, нужно использовать .read_to_string
:
reader.read_to_string(&mut buffer).unwrap();
Следующая ошибка: опять не найденный метод:
<anon>:47:44: 47:55 error: no method named `try_clone` found for type `(std::net::tcp::TcpStream, std::net::addr::SocketAddr)` in the current scope
<anon>:47 self::handle_client(stream.try_clone().unwrap(),clients); // последний в списке, данная нумерация будет его ID
^~~~~~~~~~~
И это потому, что stream - это кортеж (компилятор сам говорит (std::net::tcp::TcpStream, std::net::addr::SocketAddr)
). Соответственно, делаем так:
self::handle_client(stream.0.try_clone().unwrap(),clients); // последний в списке, данная нумерация будет его ID
Далее
<anon>:47:67: 47:74 error: mismatched types:
expected `alloc::arc::Arc<std::sync::mutex::Mutex<collections::vec::Vec<std::net::tcp::TcpStream>>>`,
found `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<std::net::tcp::TcpStream>>`
(expected struct `alloc::arc::Arc`,
found struct `std::sync::mutex::MutexGuard`) [E0308]
<anon>:47 self::handle_client(stream.0.try_clone().unwrap(),clients); // последний в списке, данная нумерация будет его ID
^~~~~~~
clients
- это MutexGuard
, и он преобразуется в &Mutex
, но вообще это так не будет работать, т.к. ты пытаешься позаимствовать self.clients
с правом изменения, а затем ещё отдать кому-то ссылку в другой поток ниже, когда делаешь thread::spawn
. Нужно ограничить время жизни изменяемой ссылки так, что когда ты отдаёшь ссылку на clients
в другой поток, ссылка на них с правом изменения уже не существует.
Поэтому, с одной стороны, переписываем функцию
fn client_loop(&self) {
let mut listener = TcpListener::bind("127.0.0.1:5653").unwrap();
loop {
let mut stream = listener.accept().unwrap();
let len;
{
let mut clients = self.clients.lock().unwrap();
clients.push(stream.0);
len = clients.len() - 1 as usize;
}
thread::spawn(move || {
self::handle_client(stream.0.try_clone().unwrap(), &*self.clients);
});
}
}
а с другой, меняем сигнатуру handle_client
на
fn handle_client(client:TcpStream, clients: &Mutex<Vec<TcpStream>>) {
Ну и упираемся в ошибку времени жизни:
<anon>:49:13: 49:26 error: the type `[closure@<anon>:49:27: 51:14 stream:(std::net::tcp::TcpStream, std::net::addr::SocketAddr), self:&server]` does not fulfill the required lifetime [E0477]
<anon>:49 thread::spawn(move || {
^~~~~~~~~~~~~
note: type must outlive the static lifetime
Поскольку окружение замыкания должно иметь время жизни 'static
(т.к. другой поток может пережить функцию, откуда он запускается), нельзя давать ссылку напрямую на поле структуры. Можно было бы попытаться положить self.clients
в Arc
, но это вызвало бы перемещение, и структура стала бы частично не валидной - компилятор этого не допустит.
Поэтому вопрос: зачем потоку обработки клиента иметь доступ ко всему вектору клиентов? Я бы ожидал, что он должен иметь ссылку только на 1 TcpStream
.