Rust、pcap 和 tokio

问题描述 投票:0回答:1

我可能采取了完全错误的方法,但我有一个 Rust 程序,它利用 pcap 板条箱读取数据包。

在主线程中,我有以下代码:

let packet = match active_capture.next_packet() {
                Ok(received) => received,
                Err(error) => { // ignore errors for example...
                    continue;
                }
            };

我正在生成几个 tokio 线程:

tokio::spawn(async move {
    // do magic stuff here
    let packet_data = bytes_from_magic;
    active_capture.sendpacket(packet_data).expect("Error sending packet.");
});

我已经经历了几次解决方案的迭代才能完成这项工作。我将 active_capture 封装在 ArcMutex 中,但在网络负载较重的情况下,性能并不理想。尝试用 RefCell 包装它会引发错误,因为 Rc 没有实现 tokio 所需的“发送”功能。

我的理解是,pcap 对于我的用例来说实际上是线程安全的,所以我想完全避免 ArcMutex,但我尝试过的任何方法都不起作用。

我正在发送第 2 层数据包,这就是我使用 pcap 的原因。如果有人有任何建议,我将不胜感激。

rust pcap tokio
1个回答
0
投票

在 Rust 中编写并发代码有两种方法:同步和异步。 通过同步并发,您可以在操作系统线程上运行可能阻塞的代码。 通过异步并发,您可以运行返回 futures 的代码,而不是在异步运行时阻塞(tokio 是最流行的 rust 异步运行时)。

如果没有看到你的代码,我不能肯定地说,但你的程序可能很慢,因为你在 tokio 协程上运行阻塞操作。 tokio 调度程序是协作式的,如果协程阻塞,它可以无限期地占用 tokios 线程之一(在单线程运行时,这意味着没有其他协程可以运行)。

一个简单的解决方法是使用

tokio::spawn_blocking
运行你的协程。这告诉 tokio 为您的协程使用单独的线程,使其他协程不受干扰。但是...

我会重新考虑异步并发是否是您的正确选择。异步编程最初是为了解决“C10k 问题”而引入的——在一定数量的线程上复用许多短期工作项。 Tokio 在这方面做得很好,但在我看来,所有 IO 都是通过单个文件描述符上的阻塞操作发生的。编写基于操作系统线程的同步程序听起来是一个更好的选择。

© www.soinside.com 2019 - 2024. All rights reserved.