2.4 libpcap和dpdk的区别

 **libpcap** 和 **DPDK** 都能用于抓取和处理网络数据包,但它们的设计目标和使用场景差异较大。让我们来分析一下它们之间的区别,以及是否可以基于 **libpcap** 实现用户态协议栈。

**libpcap** 简介:

- **用途**:libpcap 主要用于在用户态捕获网络接口上的数据包,通常用于网络分析、调试和网络监控工具(如 Wireshark、tcpdump)。

- **工作方式**:libpcap 使用的是操作系统提供的网络接口,如 Linux 的 `PF_PACKET` 套接字。它通过操作系统内核处理的数据包抓取网络数据包,提供一个缓冲区供用户态读取。

- **性能**:由于 libpcap 依赖于内核的网络协议栈和数据包处理机制,因此在性能上受限。每次数据包从网卡到达用户态需要经过内核态和用户态的切换,这会产生较大的开销,特别是在高吞吐量的网络环境中,性能瓶颈明显。

- **实现用户态协议栈**:libpcap 确实可以用来捕获原始数据包,理论上你可以在用户态实现自己的协议栈,例如 TCP/IP 协议栈。但是,由于 libpcap 本质上仍然依赖内核来传递数据包,它并不适合高性能的网络协议栈开发。而且它只能抓取和注入数据包,无法绕过内核的完整网络协议栈直接访问硬件。

**DPDK** 简介:

- **用途**:DPDK(Data Plane Development Kit)是专为高性能网络数据包处理而设计的框架,常用于需要极高吞吐量和低延迟的场景,如软件交换机、路由器、虚拟化环境中的数据转发等。

- **工作方式**:DPDK 通过绕过内核网络协议栈直接与网卡硬件交互。它使用轮询(polling)方式从网卡缓冲区中读取数据包,避免了内核态和用户态的上下文切换,因此大大提升了数据包处理的性能。DPDK 通过专门的驱动程序(如 `igb_uio` 和 `vfio-pci`)直接访问网卡的硬件资源。

- **性能**:DPDK 的设计是为了最大化网络吞吐量和减少延迟。它能够以每秒数千万乃至数亿个数据包的速度处理网络流量,这在高性能场景中有明显优势。DPDK 的零拷贝、轮询处理等机制使它成为实现高性能用户态协议栈的理想选择。

- **实现用户态协议栈**:DPDK 非常适合用于构建用户态协议栈。因为它能够完全绕过内核,将网卡的数据直接交给用户态处理程序处理,并且提供了丰富的 API 支持,如队列管理、内存管理和数据包分发等,适合构建各种网络功能模块。

### **libpcap 与 DPDK 的主要区别**:

1. **设计目标**:

   - **libpcap**:主要用于网络抓包和分析工具,关注易用性和兼容性。

   - **DPDK**:专为高性能数据包处理而设计,主要用于需要极高吞吐量和低延迟的应用。

2. **性能**:

   - **libpcap**:依赖内核协议栈,性能受到内核态和用户态切换的影响,适合低流量场景。

   - **DPDK**:直接与网卡硬件交互,极大提高了数据包处理性能,适合高流量和低延迟场景。

3. **实现协议栈**:

   - **libpcap**:虽然可以抓取原始数据包,但并不适合高性能协议栈的开发,因为数据包仍需经过内核处理。

   - **DPDK**:更适合开发高性能用户态协议栈,能够完全绕过内核,提供更高效的数据包处理能力。

4. **易用性**:

   - **libpcap**:相对简单,易于上手,特别适合网络调试和抓包。

   - **DPDK**:学习曲线较高,需要深入理解底层硬件和网络处理机制,但性能非常强大。

### 总结:

- 如果你只是想简单地抓取和分析网络数据包,**libpcap** 是一个很好的选择。

- 如果你想开发高性能用户态协议栈,**DPDK** 则是更好的选择,因为它可以绕过内核处理,直接高效地与网卡交互。

如果你对实现用户态协议栈感兴趣,DPDK 是非常适合的工具,但它的学习成本较高。你可以先从简单的 DPDK 示例程序入手,逐步理解它的处理流程。

libpcap示例:

1. 接收

抓取网卡报文,如果是tcp协议,则打印MAC IP PORT

#include <pcap.h>
#include <stdio.h>
#include <arpa/inet.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>/* 以太网头部 */
struct ethheader {u_char ether_dhost[6]; // 目的MAC地址u_char ether_shost[6]; // 源MAC地址u_short ether_type;     // 以太网类型
};/* 打印MAC地址 */
void print_mac_address(const char* desc, const u_char* mac) {printf("%s: %02x:%02x:%02x:%02x:%02x:%02x\n", desc, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}/* 打印IP地址和端口 */
void print_ip_port(const struct ip* iph, const struct tcphdr* tcph) {struct in_addr src_ip = iph->ip_src;struct in_addr dest_ip = iph->ip_dst;printf("Source IP: %s\n", inet_ntoa(src_ip));printf("Destination IP: %s\n", inet_ntoa(dest_ip));printf("Source Port: %d\n", ntohs(tcph->source));printf("Destination Port: %d\n", ntohs(tcph->dest));
}/* 数据包处理回调函数 */
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet) {struct ethheader *eth = (struct ethheader *)packet;// 检查是否是IP包if (ntohs(eth->ether_type) == ETHERTYPE_IP) {struct ip *iph = (struct ip *)(packet + sizeof(struct ethheader));// 检查是否是TCP协议if (iph->ip_p == IPPROTO_TCP) {struct tcphdr *tcph = (struct tcphdr *)(packet + sizeof(struct ethheader) + sizeof(struct ip));// 打印MAC地址print_mac_address("Source MAC", eth->ether_shost);print_mac_address("Destination MAC", eth->ether_dhost);// 打印IP地址和端口号print_ip_port(iph, tcph);}}
}int main() {char errbuf[PCAP_ERRBUF_SIZE];pcap_if_t *alldevs, *dev;pcap_t *handle;// 获取所有网络设备if (pcap_findalldevs(&alldevs, errbuf) == -1) {printf("Error finding devices: %s\n", errbuf);return 1;}// 选择第一个网络设备dev = alldevs;if (dev == NULL) {printf("No devices found\n");return 1;}// 打开设备进行捕获handle = pcap_open_live(dev->name, BUFSIZ, 1, 1000, errbuf);if (handle == NULL) {printf("Couldn't open device %s: %s\n", dev->name, errbuf);return 1;}// 捕获数据包pcap_loop(handle, 0, packet_handler, NULL);// 关闭设备pcap_freealldevs(alldevs);pcap_close(handle);return 0;
}

2. 发送

**libpcap** 不仅可以抓取网络数据包,还可以通过注入(发送)数据包到网络接口。这意味着你可以使用 libpcap 不仅进行网络数据包的捕获,还可以发送自定义的数据包。

**libpcap** 提供的函数 `pcap_inject()` 和 `pcap_sendpacket()` 可以用于发送数据包。这两个函数都可以将构造好的原始数据包发送到指定的网络接口上。

### **pcap_sendpacket()** 和 **pcap_inject()** 的区别:

- **pcap_sendpacket()**: 直接发送数据包到网络接口,但没有返回已发送的字节数。如果发送成功返回 0,失败返回 -1。

- **pcap_inject()**: 发送数据包到网络接口并返回已发送的字节数。成功时返回发送的字节数,失败时返回 -1。

### 示例代码:使用 **libpcap** 发送自定义数据包

下面是一个使用 `pcap_sendpacket()` 发送自定义以太网数据包的简单示例:

#include <pcap.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/ether.h>
#include <netinet/ip.h>
#include <netinet/udp.h>/* 以太网头部 */
struct ethheader {u_char ether_dhost[6]; // 目的MAC地址u_char ether_shost[6]; // 源MAC地址u_short ether_type;    // 以太网类型
};/* 构造一个简单的以太网数据包并发送 */
int main() {pcap_t *handle;char errbuf[PCAP_ERRBUF_SIZE];char *dev = NULL; // 设置你的设备名,例如 "eth0"// 获取第一个可用设备dev = pcap_lookupdev(errbuf);if (dev == NULL) {printf("Couldn't find default device: %s\n", errbuf);return 1;}// 打开网络设备handle = pcap_open_live(dev, BUFSIZ, 1, 1000, errbuf);if (handle == NULL) {printf("Couldn't open device %s: %s\n", dev, errbuf);return 1;}// 构造数据包(自定义以太网帧)u_char packet[42]; // 以太网头部 + IP头部 + UDP头部memset(packet, 0, sizeof(packet));// 以太网头部struct ethheader *eth = (struct ethheader *) packet;// 设置目的MAC地址eth->ether_dhost[0] = 0xff;eth->ether_dhost[1] = 0xff;eth->ether_dhost[2] = 0xff;eth->ether_dhost[3] = 0xff;eth->ether_dhost[4] = 0xff;eth->ether_dhost[5] = 0xff;// 设置源MAC地址(可以自定义)eth->ether_shost[0] = 0x00;eth->ether_shost[1] = 0x0c;eth->ether_shost[2] = 0x29;eth->ether_shost[3] = 0x12;eth->ether_shost[4] = 0x34;eth->ether_shost[5] = 0x56;eth->ether_type = htons(ETHERTYPE_IP); // IP协议// 发送数据包if (pcap_sendpacket(handle, packet, sizeof(packet)) != 0) {printf("Error sending packet: %s\n", pcap_geterr(handle));return 1;}printf("Packet sent successfully!\n");// 关闭设备pcap_close(handle);return 0;
}

### 代码说明:

1. **以太网头部**:通过 `ethheader` 结构自定义源和目的 MAC 地址,并指定以太网类型为 IP (`ETHERTYPE_IP`)。

2. **发送函数**:使用 `pcap_sendpacket()` 发送数据包,该函数会将构造好的数据包直接发送到网络接口。

3. **设备选择**:通过 `pcap_lookupdev()` 获取默认设备,也可以手动指定设备名(如 "eth0")。

3.使用步骤:

1. 确保安装了 `libpcap` 库:

   ```bash

   sudo apt-get install libpcap-dev

   ```

2. 编译程序:

   ```bash

   gcc -o send_packet send_packet.c -lpcap

   ```

3. 以管理员权限运行程序,因为发送原始数据包通常需要 root 权限:

   ```bash

   sudo ./send_packet

   ```

### 注意事项:

- **权限问题**:发送原始数据包通常需要 root 权限,因此需要以 `sudo` 运行程序。

- **网络接口**:确保选择了正确的网络接口。如果不确定,可以使用 `ifconfig` 或 `ip a` 查看网络接口名。

### 总结:

- **libpcap** 确实可以用于发送报文,通过 `pcap_sendpacket()` 和 `pcap_inject()` 可以将构造好的原始数据包发送到指定的网络接口。

- **libpcap** 的发送能力通常用于测试、网络分析等工具的开发,但并不适合高性能场景。如果你需要频繁地高性能发送数据包,可能需要考虑使用像 **DPDK** 这样的框架。


Sign in · GitLab

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/493528.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

全志H618 Android12修改doucmentsui鼠标单击图片、文件夹选中区域

背景: 由于当前的文件管理器在我们的产品定义当中,某些界面有改动的需求,所以需要在Android12 rom中进行定制以符合当前产品定义。 需求: 在进入File文件管理器后,鼠标左击整个图片、整个文件夹可以选中该类型,进行操作,故代码分析以及客制化如下: 主要涉及的代码:…

堆【Lecode_HOT100】

文章目录 1.数组中的第&#xff2b;个最大元素No.2152.前K个高频元素347 1.数组中的第&#xff2b;个最大元素No.215 方法一&#xff1a;NlogN不能满足时间复杂度的要求 public int findKthLargest(int[] nums, int k) {Arrays.sort(nums);return nums[nums.length-k];}方法二&…

Android 搭建AIDL Client和Server端,双向通信

一、背景 使用AIDL,搭建Client和Server端,实现跨进程通讯,即两个应用之间可以相互通讯。这里列举AIDL实现的方式和需注意的细节&#xff0c;并附上源码。 二、实现方式 2.1 定义AIDL需要的接口,名字为xxx.aidl,Client和Server端 AIDL接口的包名和aidl文件必须一致&#xff0c…

HIPT论文阅读

题目《Scaling Vision Transformers to Gigapixel Images via Hierarchical Self-Supervised Learning》 论文地址&#xff1a;[2206.02647] Scaling Vision Transformers to Gigapixel Images via Hierarchical Self-Supervised Learning 项目地址&#xff1a;mahmoodlab/HI…

[ESP]从零开始的Arduino IDE安装与ESP环境配置教程

一、前言 最近也是在比赛方面比较忙&#xff0c;没有更多的时间和精力去更新长文章了。这几周都更倾向于环境搭建的教程&#xff0c;这类教程写起来确实方便&#xff0c;也不怎么费时间&#xff0c;一个下午基本可以搞定&#xff0c;哈哈&#xff0c;我保证不是在为自己想摆烂找…

投标心态:如何在“标海战术”中保持清醒的头脑?

在竞争激烈的市场环境下&#xff0c;“标海战术”——即大规模参与投标——已经成为许多企业争取市场份额的重要策略。然而&#xff0c;盲目追求投标数量可能导致资源浪费、团队疲劳以及战略目标的模糊化。在这种高强度的竞争模式中&#xff0c;如何保持清醒的头脑&#xff0c;…

wxWidgets使用wxStyledTextCtrl(Scintilla编辑器)的正确姿势

开发CuteMySQL/CuteSqlite开源客户端的时候&#xff0c;需要使用Scintilla编辑器&#xff0c;来高亮显示SQL语句&#xff0c;作为C/C领域最成熟稳定又小巧的开源编辑器&#xff0c;Scintilla提供了强大的功能&#xff0c;wxWidgets对Scintilla进行包装后的是控件类&#xff1a;…

【原生js案例】让你的移动页面实现自定义的上拉加载和下拉刷新

目前很多前端UI都是自带有上拉加载和下拉刷新功能,按照官网配置去实现即可,比如原生小程序,vantUI等UI框架,都替我们实现了内部功能。 那如何自己来实现一个上拉加载和下拉刷新的功能? 实现效果 不用浏览器的css滚动条,自定义实现滚动效果 自定义实现滚动,添加上拉加载…

批处理理解

初识批处理 如何批处理&#xff1a; 命名&#xff1a;.bat 方法&#xff1a;创建一个记事本文件&#xff0c;然后将其扩展改为.bat 批处理作用&#xff1a;自上而下成批处理每一条DOS命令&#xff0c;直到执行到最后一条。运行环境&#xff1a;当然是我们cmd了 回归我学过的…

APM32F411使用IIS外设驱动es8388实现自录自播

前言&#xff1a; 从零开始学习I2s外设&#xff0c;配置Es8288寄存器实现录音播放。本文章使用主控芯片是APM32F411系类。音频相关的概念比较多&#xff0c;就不再次做过多的介绍&#xff0c;本文章只是简单实现边录边播功能。APM系类兼容st的芯片&#xff0c;所以用st的hal库来…

OB删除1.5亿数据耗费2小时

目录 回顾&#xff1a;mysql是怎么删除数据的&#xff1f; 删除方案 代码实现 执行结果 结论 本篇是实际操作 批量处理数据以及线程池线程数设置 记录学习 背景&#xff1a;有一张用户标签表&#xff0c;存储数据量达4个亿&#xff0c;使用OceanBase存储&#xff0c;由于…

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕

20241217使用M6000显卡在WIN10下跑whisper来识别中英文字幕 2024/12/17 17:21 缘起&#xff0c;最近需要识别法国电影《地下铁》的法语字幕&#xff0c;使用 字幕小工具V1.2【whisper套壳/GUI封装了】 无效。 那就是直接使用最原始的whisper来干了。 当你重装WIN10的时候&#…

linux普通用户使用sudo不需要输密码

1.root用户如果没有密码&#xff0c;先给root用户设置密码 sudo passwd root #设置密码 2.修改visudo配置 su #切换到root用户下 sudo visudo #修改visudo配置文件 用户名 ALL(ALL) NOPASSWD: ALL #下图所示处新增一行配置 用户名需要输入自己当前主机的用户名

【C++11】可变模板参数

目录 可变模板的定义方式 参数包的展开方式 递归的方式展开参数包 STL中的emplace相关接口函数 STL容器中emplace相关插入接口函数 ​编辑 模拟实现&#xff1a;emplace接口 C11的新特性可变参数模板能够让您创建可以接受可变参数的函数模板和类模板&#xff0c;相比 C9…

python 曲线拟合,曲线拟合交点

目录 效果图: 源代码: 效果图: 源代码: import json import os import shutilimport cv2 import numpy as npfrom numpy.polynomial.polynomial import Polynomialdef calculate_distance(x1, y1, x2, y2):return np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)def get_new_g…

Java模拟Mqtt客户端连接Mqtt Broker

Java模拟Mqtt客户端基本流程 引入Paho MQTT客户端库 <dependency><groupId>org.eclipse.paho</groupId><artifactId>org.eclipse.paho.mqttv5.client</artifactId><version>1.2.5</version> </dependency>设置mqtt配置数据 …

圣诞快乐(h5 css js(圣诞树))

一&#xff0c;整体设计思路 圣诞树h5&#xff08;简易&#xff09; 1.页面布局与样式&#xff1a; 页面使用了全屏的黑色背景&#xff0c;中央显示圣诞树&#xff0c;树形由三层绿色的三角形组成&#xff0c;每一层的大小逐渐变小。树干是一个棕色的矩形&#xff0c;位于三角…

多音轨视频使用FFmpeg删除不要音轨方法

近期给孩子找宫崎骏动画&#xff0c;但是有很多是多音轨视频但是默认的都是日语&#xff0c;电视上看没办法所以只能下载后删除音轨文件只保留中文。 方法分两步&#xff0c;先安装FFmpeg在转文件即可。 第一步FFmpeg安装 FFmpeg是一个开源项目&#xff0c;包含了处理视频的…

时空信息平台架构搭建:基于netty封装TCP通讯模块(IdleStateHandler网络连接监测,处理假死)

文章目录 引言I 异步TCP连接操作II 心跳机制:空闲检测(读空闲和写空闲)基于Netty的IdleStateHandler类实现心跳机制(网络连接监测)常规的处理假死健壮性的处理假死方案引言 基于netty实现TCP客户端:封装断线重连、连接保持 https://blog.csdn.net/z929118967/article/de…

中国新能源汽车公共充电桩数据合集(2002-2023年)

数据来源&#xff1a;全国各省市统计年鉴、统计公报、国家能源署、中国汽车行业协会&#xff0c;各类汽车统计年鉴、中国电动汽车充电基础设施促进联盟等 时间跨度&#xff1a;新能源汽车数据集&#xff1a;2002-2023年&#xff08;不同数据时间跨度有差异&#xff0c;详见数据…