我正在研究一个简单的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/

10-11 23:05
查看更多