C/C++
文章平均质量分 76
SilentSlot
这个作者很懒,什么都没留下…
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
【C/C++】从网卡到 socket:一个 DPDK 用户态协议栈的整体架构
I/O lcore 与协议 lcore 通过全局 ring 交换 mbuf,协议线程再借助每个 socket 的 ring、TCP 缓冲和 eventfd,把结果交给应用。这样一来,KNI 为本机流量和用户态未处理的报文保留内核去向,Netlink 把 Linux 已有的路由控制面结果同步给 DPDK FIB,协议线程负责实际的转发查表。awesome-stack 需要协调的,正是这几种不同的节奏:网卡按批次收发,协议线程按连接维护状态,应用则按 socket 和 epoll 语义工作。原创 2026-08-11 18:14:27 · 405 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(十二):TCP 并发与自实现 epoll 的就绪事件分发
DPDK 负责高性能报文收发,TCP 状态机把包转为 socket 数据,epoll 再把 socket 数据转为应用可等待的事件。三层之间通过明确的队列和所有权衔接,才能在并发连接下既快又可维护。它展示了 epoll 的本质:注册表记录“关心什么”,就绪队列记录“现在有什么可处理”,等待者只从就绪队列取事件。使用红黑树查找注册项,使用链表维护 ready list,并分别对树与就绪表设置同步机制。,用于与 Linux 系统调用区分。则要在 FIN、RST、队列错误等状态转移中明确生成,不能凭空假定。原创 2026-07-28 18:23:01 · 62 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(十一):基于 PPS、SYN 比例和源 IP 熵的 DDoS 检测
将检测逻辑放在高速包路径中:以一秒为统计窗口,计算包速率、TCP SYN 占比与源 IP 分布的 Shannon 熵。熵检测回答的是“流量分布是否异常”,SYN 比例回答的是“连接意图是否异常”,PPS 回答的是“强度是否异常”。单源或少量源集中时,熵降低。课程代码先将源 IP 做轻量 hash 后映射到 256 个桶,再遍历非零桶累计熵。这里的检测函数只做观察,不应该在数据面直接“一键全丢包”:误报会造成比攻击更严重的业务中断。仅应在明确授权、隔离的靶场执行,绝不能对公网或未授权主机压测。原创 2026-07-28 18:20:20 · 71 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(十):DPDK 接入 dnspod-sr,实现高性能 DNS UDP 处理
DPDK DNS 的价值在于把最热的 UDP 接入路径移到用户态,同时复用成熟 DNS 业务处理。设计重点是将原始 DNS payload 和网络返回路径的 peer 元数据一起跨线程传递。保存客户端 MAC、客户端 IP/端口和服务端 IP/端口。DNS payload 本身不含二层地址,因此这份元数据是响应能正确回到客户端的关键。这段失败释放非常重要:ring 满时发送线程还没接管 mbuf,当前函数仍拥有它。起步,避免压测机先耗尽端口、套接字或内存,再逐步提高负载。将高速 UDP 收包与。原创 2026-07-28 18:11:24 · 45 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(九):KNI 把未接管流量交回 Linux 内核
它适合原型和兼容场景,但新项目需注意 DPDK 版本对 KNI 的支持状态;KNI 是“选择性接管”的桥梁:加速路径在 DPDK,兼容路径留给成熟的 Linux 协议栈。关键不是把所有包一股脑送 KNI,而是明确分类、所有权和回退策略。的目标不是让 DPDK 处理所有协议,而是把不需要用户态加速的流量交还给 Linux:UDP 等目标流量走 DPDK,其他流量经 KNI 回到内核协议栈。DPDK 绑定物理网卡后,内核不再直接收到该口的包。要持续调用,才能响应内核侧的控制请求。原创 2026-07-28 18:03:47 · 91 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(七):用 rte_ring 拆出物理层、协议栈层和应用层
先用 pps、平均/尾延迟、丢包率和队列占用定位瓶颈。三层架构的收益是职责清晰和可独立扩展:协议层不再被应用阻塞,应用不再直接占用 RX 轮询。否则会出现隐蔽的数据竞争。是无锁/低锁环形队列,支持 SP/SC、MP/MC 等生产消费模式。为每个队列明确一条规则:入队成功后由消费者释放,入队失败则由当前线程释放或重试。没有这条规则,队列满时最容易产生泄漏、重复释放或“发送后又释放”的 use-after-free。随着 ARP、UDP、TCP 处理加入同一轮询循环,网卡收发、协议解析和业务逻辑会相互阻塞。原创 2026-07-28 17:53:28 · 112 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(六):TCP 三次握手、状态机与数据回显
这个版本适合作为 TCP 状态机起点,但尚未覆盖重传定时器、滑动窗口、乱序重组、拥塞控制、TIME_WAIT 管理、RST、MSS/窗口缩放协商和完整校验。手写 TCP 最有价值的部分不在“拼出一个 SYN+ACK”,而在于把每个输入报文映射为明确状态转移、序列号更新和应用可见事件。在 UDP 的 socket/ring 框架上加入 TCP 状态、序列号、确认号与标志位。数据到达时先排队 ACK,再将 payload 投递给应用,能让“确认网络数据”和“业务处理”解耦。纯 ACK 不消耗序列号。原创 2026-07-28 17:42:12 · 173 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(五):用 mbuf 实现 UDP 的 bind、recvfrom 与 sendto
课程实现清楚展示了用户态 UDP 的最小路径,但生产实现还应补上:UDP 长度与 mbuf 边界校验、队列满时的回压策略、IPv4 选项/分片处理、套接字并发保护,以及按 NUMA/lcore 分片的 socket 表。UDP 阶段把协议解析、逻辑 socket、ring 和条件变量串起来:RX 线程负责快,应用线程负责业务。关键点是 socket 层不持有原始 mbuf:协议线程解析后复制应用需要的元数据与负载,随后释放 mbuf。先填字段,将 IP 校验和、UDP 校验和清零,再分别调用。原创 2026-07-28 17:34:40 · 224 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(四):实现 ICMP Echo Reply,让 ping 通起来
Echo Request/Reply 是最适合验证三层收发正确性的协议:不需要端口和连接状态,但要求正确交换地址并重算校验和。成功意味着:主机已通过 ARP 找到 DPDK 网卡 MAC,DPDK 正确解析 IPv4/ICMP,且回包的以太网头、IP 头与 ICMP 校验和全部有效。它验证了偏移解析、网络字节序、校验和和回包地址交换,为 UDP、TCP 的组包与分发打下了同一套基础。原地回包可减少一次分配,但一定要在发送前同时交换二层和三层地址,并在所有字段更新完成后重新计算校验和。原创 2026-07-28 17:17:29 · 169 阅读 · 0 评论 -
【C/C++】手写 DPDK 协议栈(三):ARP 请求识别、应答与 ARP 表
最容易遗漏的是字节序、仅响应本机目标 IP,以及未命中 ARP 表时不能直接构造单播数据包。实际代码中应保留请求方地址的临时副本再覆盖字段,避免先写后读导致地址丢失。发送方向若找不到目标 MAC,应先广播 ARP Request,缓存或重试原业务包。ARP 正是完成“IP 地址到 MAC 地址”映射的二层协议。,且 ARP 请求的目标 IP 是本机 IP。收到请求后,交换双方 MAC/IP 并把操作码改为应答。,后续 UDP/TCP 模块也复用了 ARP 表和 ARP 组包逻辑。原创 2026-07-28 17:03:23 · 246 阅读 · 0 评论 -
【C/C++】DPDK 基础使用:从 EAL 初始化到 RX/TX 队列收发数据
本文介绍了DPDK基础使用方法,从EAL初始化到数据包收发流程。核心内容包括:1)初始化顺序必须遵循EAL、内存池、端口配置、队列设置的步骤;2)通过rte_eth_rx_burst接收数据包,利用rte_pktmbuf_mtod解析协议头;3)使用rte_pktmbuf_alloc分配内存并填充数据后,通过rte_eth_tx_burst发送数据包。文章还强调了mbuf管理和协议处理要点,并指出六个关键API构成了DPDK的核心框架,为后续网络协议开发奠定了基础。原创 2026-07-28 16:57:08 · 175 阅读 · 0 评论 -
【C/C++】从零配置 DPDK 实验环境:巨页、VMware 网卡、驱动加载与 PCI 绑定
环境成功的判据不是“模块已加载”,而是:巨页可用、目标 PCI 被 UIO/VFIO 接管、程序能枚举端口,且宿主机能向该 MAC 发出测试流量。代价是环境必须一次配对:CPU、巨页、IOMMU/驱动和 PCI 网卡缺一不可。页面大小和数量要根据 mbuf 数量、NUMA 和可用内存调整,不能在生产主机上盲目照搬。若接口将由 DPDK 独占,则无需配置 IP。这样主机知道目标 MAC,报文才会被发往被 DPDK 接管的虚拟网卡。网卡通过 DMA 直接读写预分配的大页内存,减少中断、系统调用和数据拷贝。原创 2026-07-28 16:46:13 · 180 阅读 · 0 评论 -
【C/C++】用户态协议栈如何实现 epoll:红黑树、就绪队列和回调通知
用户态协议栈实现epoll的核心机制 本文介绍了在用户态协议栈中实现epoll功能的三个核心组件: 数据结构设计:使用红黑树(rbr)维护关注集合,链表(rdlist)管理就绪事件,条件变量(cond)实现等待机制。 关键操作流程: nepoll_create创建eventpoll对象并初始化数据结构 nepoll_ctl通过红黑树管理关注的socket描述符 协议栈通过回调函数将就绪事件加入就绪队列并唤醒等待线程 高效通知机制:采用"就绪通知"而非轮询方式,当socket状态变化时主动触发回调,将事件插入原创 2026-06-29 15:22:36 · 383 阅读 · 0 评论 -
【C/C++】从 DPDK 收包到用户态 TCP/IP 协议栈:一个 ustack 示例拆解
本文介绍了基于DPDK实现用户态TCP/IP协议栈的核心流程。首先明确DPDK并非协议栈,而是绕过内核直接访问网卡的工具箱。文章详细拆解了五个关键环节:(1)DPDK初始化阶段创建内存池和网卡队列;(2)主循环通过ring结构解耦收发包过程;(3)协议分发层处理Ethernet/IPv4/UDP/TCP等协议;(4)UDP报文如何进入应用缓冲区;(5)KNI机制将不处理的数据包交回内核。示例代码展示了如何从DPDK收包到实现用户态协议栈的基本框架,为构建高性能网络应用提供了参考方案。原创 2026-06-29 15:18:58 · 407 阅读 · 0 评论 -
【C/C++】从 setjmp 到 ucontext 再到 hook:C 语言协程是怎么跑起来的?
网络服务里经常有一个矛盾:课程笔记里对这个问题的概括很直接:协程要解决的就是这个问题:业务代码看起来像同步代码,底层遇到 IO 不就绪时主动让出 CPU;等 fd 就绪后,调度器再恢复它。所以协程不是为了“炫技式切栈”,而是为高并发 IO 服务:一个函数普通调用时,执行权从调用者进入被调用者;函数返回后,栈帧销毁,不能随便回到中间某一行继续执行。协程不一样。它要支持两个基本动作:课程里列了三种常见实现路线:这三种方法的核心都一样:保存 CPU 寄存器、栈信息和下一条执行位置;恢复时再把这些状态装回去。先原创 2026-06-26 22:10:07 · 445 阅读 · 0 评论 -
【C/C++】从 POSIX Socket 到 TCP 生命周期:一文理解网络 IO 的核心原理
文章摘要:理解网络IO核心原理:从POSIX Socket到TCP生命周期 本文系统梳理了C/C++网络编程的核心原理,从POSIX Socket API到TCP连接生命周期管理。主要内容包括:socket()创建文件描述符与TCP控制块,bind()绑定地址端口,listen()准备连接队列,TCP三次握手同步序列号,accept()获取已建立连接,send/recv操作内核缓冲区数据的原理。文章还介绍了epoll+Reactor模式的高效IO多路复用机制,以及边缘触发模式下非阻塞accept的注意事项。原创 2026-06-26 13:48:44 · 701 阅读 · 0 评论 -
【C/C++】C1000K 百万连接测试:Linux 参数、fd 限制和 epoll 压测客户端
很多人一提到百万连接,第一反应就是epoll。但真正测试时,epoll往往不是第一个瓶颈。README 中整理了一组面向长连接数量测试的参数。它的目标是让系统能维持大量连接,而不是追求高吞吐。原创 2026-06-25 18:05:36 · 100 阅读 · 0 评论 -
【C/C++】C 语言实现 WebSocket:握手、帧解析、掩码和回显
WebSocket 不是一开始就直接发送二进制帧,它先通过 HTTP 发起升级请求。服务端要读取,按 RFC 6455 的规则生成,再返回。之后这条 TCP 连接才进入 WebSocket 帧通信阶段。项目中的 WebSocket 状态用state == 0state == 1state == 2。原创 2026-06-25 17:54:43 · 168 阅读 · 0 评论 -
【C/C++】用 epoll 写一个 Reactor:连接对象、回调和状态机
本文介绍了用C/C++基于epoll实现Reactor模式的核心思想,重点分析了连接管理、事件注册和回调机制的设计。Reactor通过分离事件循环和业务处理解决了裸epoll代码臃肿的问题:1) 使用connection结构集中管理连接状态;2) 将epoll_ctl封装为set_event简化操作;3) 通过event_register绑定fd与回调函数;4) 主循环仅负责事件分发。文章通过WebSocket和HTTP文件传输示例,展示了如何利用状态机和读写缓冲区实现分阶段协议处理,特别是处理部分写入等网原创 2026-06-25 17:42:31 · 74 阅读 · 0 评论 -
【C/C++】select、poll、epoll 实战对比:从 fd_set 到就绪事件列表
本文对比了三种I/O多路复用技术:select、poll和epoll。通过实现TCP服务器的三个版本,展示了它们的关键特性和差异。select使用fd_set位图管理连接,需要每轮重建集合并扫描全部fd;poll改用pollfd数组,无需重建集合但仍需扫描;epoll采用事件注册机制,内核维护兴趣集合,只返回就绪事件。性能上,epoll最适合大量长连接场景。文章还提供了编译运行方法和测试指令,帮助读者实践理解这三种技术的演进过程和应用场景。原创 2026-06-25 17:14:34 · 168 阅读 · 0 评论 -
【C/C++】从 socket 到多线程 TCP Echo 服务器:fd、accept 与 recv/send 全流程
在学习网络编程时,第一道坎不是epoll,而是搞清楚服务端从“监听端口”到“处理客户端数据”到底经历了什么。这个项目里的是一个非常直接的 TCP Echo Server:客户端发什么,服务端就原样回什么。原创 2026-06-25 17:00:59 · 187 阅读 · 0 评论 -
【C/C++】多线程竞争与线程池
本文探讨多线程编程中的竞争问题与线程池管理。在多线程环境下,count++等简单操作可能因非原子性引发临界区竞争,导致数据不一致。文章对比了互斥锁、自旋锁、原子操作和CAS(比较并交换)等同步方案,指出CAS通过乐观重试避免阻塞但高竞争时效率低,不同方案需按场景选择。线程池通过任务队列、互斥锁和条件变量管理线程数量与任务调度,避免无限制创建线程。文中强调多线程编程需平衡正确性、性能和资源管理,在安全、效率和复杂度间取得平衡。附带GitHub学习资源链接。原创 2026-06-25 11:17:42 · 153 阅读 · 0 评论 -
【C/C++】TCP 服务器演进:从阻塞 accept 到 epoll 事件驱动
我的体会是,服务器模型的升级本质上是在控制资源:单线程省资源但并发弱,多线程并发直观但线程成本高,epoll 把并发压力转移到事件驱动模型上。连接少时没问题,连接很多时,每个线程都要栈空间和调度成本,系统资源会被迅速吃掉。它的核心思路不是“每个连接一个线程”,而是“一个线程监听很多 fd 的事件”。这条线跑通之后,问题马上出现:如果单线程阻塞处理,一个客户端卡住,后面的客户端就都要等。这里的关键变化是:程序不再主动挨个问每个连接有没有数据,而是把 fd 注册给内核,由。,否则没读完的数据可能再也不会提醒。原创 2026-06-25 11:10:14 · 236 阅读 · 0 评论 -
【C/C++】用 C 写 HTTP 客户端
HTTP 项目表面上是写一个 GET/POST 客户端,本质上是在练 TCP 客户端的完整流程:域名解析、建立连接、构造请求、发送数据、循环接收响应。和浏览器相比,自己用 C 写一遍会发现,HTTP 文本格式很清楚,但网络 IO 的边界情况一点都不少。我的理解是,HTTP 客户端练的不只是协议文本,更是“可靠地读完不确定长度的数据”。网络编程里,读到一半、超时、对端关闭、暂时无数据都是正常情况。,HTTP 请求行和请求头都用回车换行结束,头部结束后还要有一个空行。返回 0 判断对端关闭,简化读取逻辑。原创 2026-06-25 11:07:27 · 223 阅读 · 0 评论 -
【C/C++】用 C 语言手写 DNS 查询:理解 UDP 和协议报文
这篇150字的摘要概括了用C语言实现DNS查询的核心内容: 本文介绍了如何通过C语言手动实现DNS查询,重点解析了UDP协议和DNS报文格式。作者通过定义DNS头部结构体(dns_header)和实现域名特殊编码(长度+内容),演示了网络协议在字节层面的处理细节。项目揭示了UDP协议虽然简单,但需要开发者自行处理网络字节序转换、报文组装等底层细节。通过对比普通字符串(www.baidu.com)和DNS编码格式(3www5baidu3com0),文章生动说明了DNS协议设计的巧妙之处。该实践项目让作者深刻体原创 2026-06-25 09:41:26 · 266 阅读 · 0 评论 -
【C/C++】用状态机和字典树统计单词:从“能数”到“数得清楚”
如果只是遇到字母就加一,很快会出错,因为一个单词包含多个字母,连续字母不能重复计数。正确的想法是:遍历每个字符时,先判断自己当前处在什么状态,再根据输入字符决定是否切换状态。我的体会是,文本处理不能只盯着“字符”,还要盯着“上下文”。状态机负责识别单词边界,字典树负责保存统计结果,一个解决解析问题,一个解决存储问题。状态后,程序能表达“我刚刚在单词中遇到了横杠,下一步要看是不是换行”的中间态。这种换行断词,如果简单把横杠和换行都当成分隔符,就会把一个词误判成两个词。状态,再读到字母就不重复加。原创 2026-06-25 09:35:32 · 205 阅读 · 0 评论 -
【C/C++学习】从通讯录项目理解 C 语言里的分层设计
本文通过通讯录项目实践,阐述了C语言分层设计的重要性。项目将代码分为业务层(用户操作)、接口层(数据操作)和支撑层(存储实现),通过封装人员信息的增删查改及文件操作接口(如person_insert()、save_file()等),实现存储结构变更不影响上层逻辑。文中特别强调输入安全应使用fgets替代scanf,并指出分层设计的核心价值在于隔离变化点(如存储方式),使简单项目也能具备扩展性。该案例虽小,却完整呈现了接口抽象、数据封装等工程化思维,为后续开发复杂系统奠定基础。原创 2026-06-25 09:26:52 · 215 阅读 · 0 评论
分享