我有一个简单的客户端/服务器应用程序。我在服务器端接收来自客户端的消息,但我想将该响应发送到从服务器到其他文件的通道,我收到错误"借用的值不够长"。
我已经在堆栈溢出中搜索了类似的问题,但是没有对生存期有足够的理解。有关于这个主题的好的文档或者简单的例子吗?
现在,如果有人可以帮助我修复这个代码(可能是编辑代码中需要修复的部分),这将是有帮助的。
先谢了。
服务器端:
use std::os::unix::net::UnixDatagram;
use std::path::Path;
fn unlink_socket (path: impl AsRef<Path>) {
let path = path.as_ref();
if Path::new(path).exists() {
let result = std::fs::remove_file(path);
match result {
Err(e) => {
println!("Couldn't remove the file: {:?}", e);
},
_ => {}
}
}
}
pub fn tcp_datagram_server() {
pub static FILE_PATH: &'static str = "/tmp/datagram.sock";
let (tx, rx) = mpsc::channel();
let mut buf = vec![0; 1024];
unlink_socket(FILE_PATH);
let socket = match UnixDatagram::bind(FILE_PATH) {
Ok(socket) => socket,
Err(e) => {
println!("Couldn't bind: {:?}", e);
return;
}
};
println!("Waiting for client to connect...");
loop {
let received_bytes = socket.recv(buf.as_mut_slice()).expect("recv function failed");
println!("Received {:?}", received_bytes);
let received_message = from_utf8(buf.as_slice()).expect("utf-8 convert failed");
tx.clone().send(received_message);
}
}
fn main() {
tcp_datagram_server();
}
客户端:
use std::sync::mpsc;
use std::os::unix::net::UnixDatagram;
use std::path::Path;
use std::io::prelude::*;
pub fn tcp_datagram_client() {
pub static FILE_PATH: &'static str = "/tmp/datagram.sock";
let socket = UnixDatagram::unbound().unwrap();
match socket.connect(FILE_PATH) {
Ok(socket) => socket,
Err(e) => {
println!("Couldn't connect: {:?}", e);
return;
}
};
println!("TCP client Connected to TCP Server {:?}", socket);
loop {
socket.send(b"Hello from client to server").expect("recv function failed");
}
}
fn main() {
tcp_datagram_client();
}
我收到的错误
error[E0597]: `buf` does not live long enough
--> src/unix_datagram_server.rs:38:42
|
38 | let received_message = from_utf8(buf.as_slice()).expect("utf-8 convert failed");
| ^^^ borrowed value does not live long enough
...
41 | }
| -
| |
| `buf` dropped here while still borrowed
| borrow might be used here, when `tx` is dropped and runs the `Drop` code for type `std::sync::mpsc::Sender`
|
= note: values in a scope are dropped in the opposite order they are defined
error: aborting due to previous error; 8 warnings emitted
3条答案
按热度按时间zpqajqem1#
现在,如果有人可以帮助我修复这个代码(可能是编辑代码中需要修复的部分),这将是有帮助的。
send
确实做了它所说的事情,它通过通道 * 发送 * 参数。这意味着数据必须存活足够长的时间,并"永远"保持有效(它需要在通道中存活并有效,以及当接收方从通道中获取数据时)。这里的情况不是这样的。rustc无法理解函数永远不会返回,并且无论如何它都会死机,结果都是一样的:函数将终止,这将使
buf
无效。由于received_message
借用buf
,这意味着received_message
在函数终止后不能有效。但此时消息仍将在通道中等待读取(或被接收方检索,谁知道接收方在做什么)。因此你的建筑是不允许的。
第二个问题是你在每个循环中都会覆盖缓冲区数据,这和你在上一次迭代中发送的消息一样,也是不正确的,尽管Rust也不允许你这么做:如果您解决了第一个错误,它会告诉您有一个未完成的共享借用(通过通道发送的消息),因此您不能在下一次迭代中修改后备缓冲区。
解决办法很简单:让每个迭代创建一个 * owned * 字符串(复制当前迭代的消息)并通过通道发送:
此外,这些更多的是风格/效率低下的评论,但:
tx
上的clone()
是完全冗余的。发送方是Clone
的目的是能够从多个线程发送(因此通道名称中的 * mp * 表示 * 多个生产者 *)。这里有一个线程,原始发送方工作正常。.as_slice()
和.as_mut_slice()
,此处没有:数组引用强制指向切片,所以你可以只使用&mut buf
和&buf
,为什么要在已经是路径的东西上调用Path::new
,它什么都不做,也没有用。println
相同)。而且我不明白标记词法嵌套的static
pub
的目的。由于static
在函数内部,它甚至对函数的兄弟不可见,更不用说外部调用者了。结果我得到了这个结果:m3eecexj2#
编译器消息中有一个提示,即作用域中的值将按照与定义顺序相反的顺序删除,在本例中,
buf
定义在tx
之后,这意味着它将在tx
之前 * 删除。(以received_message
的形式)被传递到tx.send()
,则buf
应该比TX存活得更长,因此切换定义顺序将修复该特定错误(即,切换第19和20行)。5vf7fwbs3#
这里的答案是真诚的,但也有一些情况(公认的罕见),一个值永远不会超出范围,因为你的函数是要永远存在的,而Rust的借用检查器在这种情况下无法工作,因为Rust的引用不是指针。
如果你从逻辑上考虑你的代码并且绝对肯定这是事实,那么--风险自负--你可以将你的指针强制转换为一个原始指针。
buf.as_slice() as *const u8
如果它有你需要使用的方法,你需要将它强制转换回一个引用来使用它们,例如。