从一个线程到另一个线程中的Struct的TCPListener和TcpStream的引用



我目前遇到的问题是创建一种将TCPListener从线程引用到主线程的Struct的方法。我试图实现的最终目标是从server结构引用服务器的TCP连接。

这是代码:

use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::sync::{Arc, mpsc, Mutex};
use std::thread;
fn main() {
let server = Server::start("127.0.0.1:25565".to_string());
loop {
for client in server.connected_clients {
println!("{:?}", client.stream.peer_addr().unwrap())
}
}
}
#[derive(Debug)]
struct Server {
listener: Arc<Mutex<TcpListener>>,
connected_clients: Vec<Client>,
}
impl Server {
pub fn start(address: String) -> Server {
let listener = TcpListener::bind(address).unwrap();
let (tx, rx) = mpsc::channel();
let listener = Arc::new(Mutex::new(listener));
let server = Server {
listener: listener,
connected_clients: Vec::new()
};
tx.send(&server.listener).unwrap();
thread::spawn(|| {
let listener = rx.recv().unwrap();
// For each new connection start a new thread
for stream in listener.lock().unwrap().incoming() {
let mut stream = stream.unwrap();
thread::spawn(move || {
// TODO: Add client to the connected_clients Vec
let mut buffer = [0; 1024];
loop {
stream.read(&mut buffer).unwrap();
println!("{}", String::from_utf8(Vec::from(&buffer[..])).unwrap().trim_end_matches(char::from(0)));
}
});
}
});
server
}
}
#[derive(Debug)]
struct Client {
id: usize,
stream: TcpStream,
}

错误:std::sync::mpsc::Receiver<amp;弧形<Mutex>gt;`无法在线程之间安全共享

我不确定您是从哪里得到的使用channel将对象发送到刚刚生成的线程的想法,但在这种情况下肯定是不正确的。

只需使用move ||闭包将外部变量移动到其中即可

考虑到这一点,这段代码编译:(尽管我没有办法测试它是否有效(

use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
fn main() {
let server = Server::start("127.0.0.1:25565".to_string());
loop {
for client in &server.connected_clients {
println!("{:?}", client.stream.peer_addr().unwrap())
}
}
}
#[derive(Debug)]
struct Server {
listener: Arc<Mutex<TcpListener>>,
connected_clients: Vec<Client>,
}
impl Server {
pub fn start(address: String) -> Server {
let server = Server {
listener: Arc::new(Mutex::new(TcpListener::bind(address).unwrap())),
connected_clients: Vec::new(),
};
let listener = server.listener.clone();
thread::spawn(move || {
// For each new connection start a new thread
for stream in listener.lock().unwrap().incoming() {
let mut stream = stream.unwrap();
thread::spawn(move || {
// TODO: Add client to the connected_clients Vec
let mut buffer = [0; 1024];
loop {
stream.read(&mut buffer).unwrap();
println!(
"{}",
String::from_utf8(Vec::from(&buffer[..]))
.unwrap()
.trim_end_matches(char::from(0))
);
}
});
}
});
server
}
}
#[derive(Debug)]
struct Client {
id: usize,
stream: TcpStream,
}

从技术上讲,虽然在这种情况下完全是过度使用,但channel方法也可以工作,但您必须发送对象的实际实例,而不是引用。您仍然需要使用move ||闭包来将rx对象移动到其中

use std::io::Read;
use std::net::{TcpListener, TcpStream};
use std::sync::{mpsc, Arc, Mutex};
use std::thread;
fn main() {
let server = Server::start("127.0.0.1:25565".to_string());
loop {
for client in &server.connected_clients {
println!("{:?}", client.stream.peer_addr().unwrap())
}
}
}
#[derive(Debug)]
struct Server {
listener: Arc<Mutex<TcpListener>>,
connected_clients: Vec<Client>,
}
impl Server {
pub fn start(address: String) -> Server {
let listener = TcpListener::bind(address).unwrap();
let (tx, rx) = mpsc::channel();
let listener = Arc::new(Mutex::new(listener));
let server = Server {
listener: listener,
connected_clients: Vec::new(),
};
tx.send(server.listener.clone()).unwrap();
thread::spawn(move || {
let listener = rx.recv().unwrap();
// For each new connection start a new thread
for stream in listener.lock().unwrap().incoming() {
let mut stream = stream.unwrap();
thread::spawn(move || {
// TODO: Add client to the connected_clients Vec
let mut buffer = [0; 1024];
loop {
stream.read(&mut buffer).unwrap();
println!(
"{}",
String::from_utf8(Vec::from(&buffer[..]))
.unwrap()
.trim_end_matches(char::from(0))
);
}
});
}
});
server
}
}
#[derive(Debug)]
struct Client {
id: usize,
stream: TcpStream,
}

最后一句话:

不过,我对整个结构的有用性表示怀疑。一旦你的线程进入for循环,你的listener就会被持续锁定,这意味着,任何试图通过Server对象实际访问它的人都会死锁。

最新更新