【发布时间】:2017-12-21 23:23:07
【问题描述】:
我正在尝试开始使用 Rust,并试图将一些部分放在一起并拥有一个“服务器”实例,其中包含一个“客户端”向量,其中每个客户端都有一个套接字。
我知道在 Rust 中 Socket 或 TcpStream 需要是可变的,并且我需要借用引用以便在主循环中客户端实例化之后保持范围。
但我遇到的问题是我的 TcpStream 字段在 Client 结构中可能不可变。所以我不确定我的方法是否正确,但我尝试使用生命周期参数 来解决这个问题,但这导致我遇到另一个问题,即“服务器”中的“客户端”没有通过 生命周期参数。
有人可以帮我解决这个问题或告诉我解决这个问题/解决方案的正确方法吗?
谢谢。
use std::net::*;
use std::io::Write;
use std::thread;
use std::time::Duration;
struct Client<'a> {
socket: &'a mut TcpStream,
addr: SocketAddr
}
struct Server {
clients: Vec<Box<Client>>
}
impl Server {
pub fn new() -> Server {
Server{clients: Vec::new()}
}
fn write(&self, stream: &mut TcpStream) {
let mut counter: u32 = 0;
counter += 1;
stream.write(counter.to_string().as_bytes()).unwrap();
thread::sleep(Duration::from_secs(1));
}
fn client_thread(&self, client: &mut Client) {
self.write(&mut client.socket);
}
fn add_client(&self, socket: &mut TcpStream, addr: SocketAddr) {
let mut client = Client {
socket: socket,
addr: addr
};
self.clients.push(Box::new(client));
self.client_thread(&mut client);
}
pub fn server_loop(&self) {
let listener = TcpListener::bind("127.0.0.1:5001").unwrap();
loop {
match listener.accept() {
Ok((mut socket, addr)) => {
println!("new client: {:?}", addr);
thread::spawn(move || loop {
self.add_client(&mut socket, addr);
});
},
Err(e) => println!("couldn't get client: {:?}", e),
}
}
}
}
fn main() {
let mut server = Server::new();
server.server_loop();
}
更新:
当前的错误信息是:
clients: Vec<Box<Client>>
^^^^^^ expected lifetime parameter
更新 2:
现在我认为解决方案更好/更接近目标。但是我仍然对线程有问题:spawn outside static context。
use std::net::*;
use std::io::Write;
use std::thread;
struct Client {
socket: TcpStream
}
struct Server {
clients: Vec<Box<Client>>
}
impl Server {
fn new() -> Server {
Server{clients: vec![]}
}
fn write(&mut self, stream: &mut TcpStream) {
let mut counter: u32 = 0;
stream.write(counter.to_string().as_bytes()).unwrap();
}
fn client_loop(&mut self, client: &mut Client) {
loop {
self.write(&mut client.socket);
}
}
fn add_client(&mut self, s: TcpStream) {
let mut client = Client{
socket: s
};
self.clients.push(Box::new(client));
println!("New client: {}", client.socket.peer_addr().unwrap());
thread::spawn(move || {
self.client_loop(&mut client);
});
}
pub fn server_loop(&mut self) {
let listener = TcpListener::bind("127.0.0.1:5001").unwrap();
loop {
match listener.accept() {
Ok((socket, _addr)) => {
self.add_client(socket);
},
Err(e) => println!("Couldn't get client: {}", e),
}
}
}
}
fn main() {
let mut server = Server::new();
server.server_loop();
}
错误[E0477]:[closure@src/main.rs:38:23: 40:10 self:&mut Server, client:Client] 类型不满足所需的生命周期
--> src/main.rs:38:9
|
38 | thread::spawn(move || {
| ^^^^^^^^^^^^^
|
= note: type must satisfy the static lifetime
【问题讨论】:
-
请更具体地说明您的问题。一个好的minimal reproducible example 通常包含从编译器逐字复制的错误消息。
-
坦率地说,这段代码有很多个问题。例如:您在移动某物后对其进行了引用,您尝试将对局部变量的引用传递给线程,在很多这些地方您可能想要
&mut self而不是&self,等等。你有没有阅读The Rust Programming Language?强烈推荐。 我尝试使用生命周期参数<'a>来解决这个问题——生命周期不是这样做的。同样,这本书将解释什么是生命周期。通过疯狂地折腾来学习 Rust 并不容易或有趣。 -
嗨@E_net4,很抱歉没有提供更好的细节,现在将添加错误消息。
-
嗨@Shepmaster,非常感谢您对阅读的建议,现在将阅读。你所说的使用真的很有意义,我会努力改进。但在此期间,您能否帮助我解决上述错误,其结构包含 Vec 包含 Client?