我正在研究一个简单的Rust程序,该程序可以读取和解析网络数据包。为了读取网络数据包,我使用了pnet libary。
因为解析可能要花一些时间,所以我使用了两个单独的线程来读取和解析数据包。
我现在的想法是通过消息传递(使用mpsc::channel()
)将读取的包从第一个线程传递到第二个线程。
这是我基于the example given in the pnet doc编写的代码的简化版本:
extern crate pnet;
use std::sync::mpsc;
use std::thread;
use pnet::datalink;
use pnet::datalink::Channel::Ethernet;
fn main() {
let (sender, receiver) = mpsc::channel();
thread::spawn(move || {
for packet in receiver.recv() {
println!("{:?}", packet)
}
});
let interface = datalink::interfaces().into_iter()
.find(|interface| interface.name == "enp5s0")
.unwrap();
let (_, mut package_receiver) =
match datalink::channel(&interface, Default::default()) {
Ok(Ethernet(tx, rx)) => (tx, rx),
_ => panic!()
};
loop {
match package_receiver.next() {
Ok(packet) => {
// sender.send("foo"); // this works fine
sender.send(packet);
}
_ => panic!()
}
}
}
对于通过 channel 发送基本类型或字符串,但对于网络数据包而言,此方法效果很好。当我尝试通过 channel 将数据包发送到解析器线程时,出现以下编译器错误:
error[E0597]: `*package_receiver` does not live long enough
--> src/main.rs:28:15
|
28 | match package_receiver.next() {
| ^^^^^^^^^^^^^^^^ borrowed value does not live long enough
...
36 | }
| - borrowed value only lives until here
|
= note: borrowed value must be valid for the static lifetime...
我对Rust还是很陌生,非常感谢您的帮助!
最佳答案
packet
是&[u8]
类型,其生命周期'a
也与package_receiver
调用中对next()
的引用相同。具有生存期的next()
定义将如下所示:
fn next(&'a mut self) -> Result<&'a [u8]>
您将
send
&[u8]
到一个线程。但是线程可能会超过您发送给它的引用,从而导致引用悬空。结果,编译器提示他们需要具有'static
生存期。 "foo"
有效,因为它是&'static str
。一种方法是获取数据的所有权,然后将其作为值发送到另一个线程。
Ok(packet) => {
// sender.send("foo"); // this works fine
sender.send(packet.to_owned());
}
您也可以看看将范围内的线程与crossbeam一起使用
关于multithreading - 使用 channel 在线程之间通信Rust pnet数据包,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53676102/