
简介这是一份面向C#开发者、网络管理员与安全分析人员的网络抓包工具源码聚焦IP、TCP、UDP数据包的捕获与解析可指定网卡与端口进行监听适合用于网络调试、协议学习与安全排查等场景。压缩包共82个文件约1.12MB以24个cs源码文件为核心配合14个png界面截图、8个resx与4个resources资源文件、2个sln解决方案及2个csproj工程文件另有exe、dll、ico等可执行与图标资源整体结构完整可直接编译运行。项目围绕Socket套接字编程展开涉及本地端点绑定、ReceiveFrom持续接收、IP/TCP/UDP头部字段解析以及时间戳、源目标地址、协议类型、端口号、数据大小等信息的格式化展示并配有过滤选项与主界面窗体。目前已有735人学习下载读者可借此理解网络通信底层机制掌握数据包捕获、解析与显示的实现思路提升网络调试与协议分析能力。1. 从一块网卡说起C# 抓包到底能拿到什么很多人第一次做 C# 抓包是因为现场设备通信出了问题上位机发出去的指令对方没回或者回了一堆看不懂的字节日志里只有「超时」两个字。这时候你需要的不是加打印而是把经过网卡的真实数据包原样捞出来看。C# 抓取 IP、TCP、UDP 网络数据包本质上是借助 WinPcap/Npcap 这类底层驱动把网卡收到的原始帧交给托管代码解析再按协议栈逐层剥开——以太网头、IP 头、TCP/UDP 头、应用层载荷。它能解决的核心问题就三个确认数据到底有没有发出去、确认对方到底回了什么、确认端口和协议有没有配对。适合做上位机、工控网关、协议对接、网络调试的从业者尤其是需要按指定端口过滤、又不想装 Wireshark 整套环境的场景。下面这份资源就是围绕这条链路拆的我按「能跑起来 → 看得懂 → 避得开坑」的顺序讲。2. 环境与选型SharpPcap 为什么是 C# 抓包的首选2.1 托管抓包库的三种路线对比C# 想抓包绕不开底层驱动。常见做法有三条路一是直接 P/Invoke 调 WinPcap 的 wpcap.dll灵活但全是裸指针稍不留神就内存泄漏二是用 SharpPcap它对 wpcap 做了完整托管封装设备枚举、过滤器、收包事件都是 C# 风格三是用 .NET 自带的 Socket 走 Raw Socket但 Windows 对 Raw Socket 限制多收不到非本机流量抓 TCP 握手都费劲。我一般直接上 SharpPcap配合 PacketDotNet 做协议解析这两个库版本要配套SharpPcap 负责「拿到字节」PacketDotNet 负责「翻译字节」。选型时要注意运行环境SharpPcap 依赖 NpcapWinPcap 已停止维护安装 Npcap 时必须勾选「WinPcap API-compatible Mode」否则 SharpPcap 枚举不到网卡。这一步是新手翻车重灾区装完没勾代码里CaptureDeviceList.Instance返回空列表还以为是代码写错了。2.2 用 NuGet 把依赖装齐新建一个 .NET 控制台或 WinForms 项目包管理器里执行# 安装抓包核心库与协议解析库版本号按项目框架选 dotnet add package SharpPcap --version 6.2.5 dotnet add package PacketDotNet --version 1.4.7装完后确认输出目录里有PacketDotNet.dll和SharpPcap.dll。如果是 .NET Framework 老项目用Install-Package命令效果一样。这里版本不是随便写的SharpPcap 6.x 对应 Npcap 1.xPacketDotNet 1.4.x 的TcpPacket、UdpPacket属性名和 6.x 的 SharpPcap 事件模型能对上混用旧版会出现Packet类型不匹配的编译错误。2.3 枚举网卡并确认抓包权限抓包前先列出所有可用设备确认目标网卡在列表里using SharpPcap; using SharpPcap.LibPcap; // 获取所有可抓包的网络接口 var devices CaptureDeviceList.Instance; if (devices.Count 0) { Console.WriteLine(未发现网卡检查 Npcap 是否勾选兼容模式); return; } // 打印每块网卡的名字和描述方便定位 for (int i 0; i devices.Count; i) { Console.WriteLine($[{i}] {devices[i].Name} - {devices[i].Description}); }CaptureDeviceList.Instance是静态属性第一次访问会触发驱动加载。如果返回 0九成是 Npcap 没装好或没勾兼容模式。Name是\Device\NPF_{GUID}格式Description才是人类可读的网卡名。生产环境里别用索引硬编码用 Description 关键字匹配更稳比如找含「Realtek」或「Intel」的那块。3. 抓包核心按指定端口过滤 TCP 与 UDP3.1 BPF 过滤器语法与端口表达式SharpPcap 的过滤器直接透传给底层 BPF 引擎语法和 tcpdump 一致。要抓指定端口核心表达式是tcp port 502或udp port 47808。多个端口用or连接比如tcp port 502 or tcp port 503。想同时抓 TCP 和 UDP 的某个端口写port 8080即可BPF 会自动匹配两种协议。这里有个容易忽略的点过滤器在驱动层生效不匹配的包根本不会进托管内存所以过滤条件写得越精确CPU 占用越低。常见做法是先宽后窄调试阶段用ip host 192.168.1.100先确认流量方向再逐步加端口条件。如果一上来就写死端口结果发现包根本没到网卡排查方向就窄了。3.2 打开设备并注册收包回调下面这段是完整的抓包主流程按指定端口过滤并解析using SharpPcap; using PacketDotNet; // 假设已选中 devices[0]打开设备准备抓包 var device devices[0]; device.Open(new DeviceConfiguration { Mode DeviceModes.Promiscuous, // 混杂模式抓经过网卡的所有帧 ReadTimeout 1000 // 读超时 1 秒避免线程卡死 }); // 设置 BPF 过滤器只抓 TCP 502 端口和 UDP 47808 端口 device.Filter tcp port 502 or udp port 47808; // 注册收包事件每来一个包触发一次 device.OnPacketArrival (sender, e) { // 从原始字节解析出以太网帧 var rawPacket Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data); var ipPacket rawPacket.ExtractIPPacket(); if (ipPacket null) return; // 按协议类型分别处理 if (ipPacket.Protocol ProtocolType.Tcp) { var tcp ipPacket.ExtractTcpPacket(); Console.WriteLine($TCP {ipPacket.SourceAddress}:{tcp.SourcePort} - ${ipPacket.DestinationAddress}:{tcp.DestinationPort} $载荷 {tcp.PayloadData?.Length ?? 0} 字节); } else if (ipPacket.Protocol ProtocolType.Udp) { var udp ipPacket.ExtractUdpPacket(); Console.WriteLine($UDP {ipPacket.SourceAddress}:{udp.SourcePort} - ${ipPacket.DestinationAddress}:{udp.DestinationPort} $载荷 {udp.PayloadData?.Length ?? 0} 字节); } }; // 开始抓包-1 表示持续抓直到手动停止 device.StartCapture(); Console.WriteLine(抓包中按回车停止...); Console.ReadLine(); device.StopCapture(); device.Close();逻辑上分四步打开设备、设过滤器、挂回调、启停控制。DeviceModes.Promiscuous是混杂模式能抓到目的地址不是本机的帧做网关分析时必须开如果只关心本机通信用DeviceModes.None更省资源。ReadTimeout设 1000 毫秒是经验值太小会导致频繁空轮询太大则停止响应慢。Packet.ParsePacket的第一个参数是链路层类型以太网就是LinkLayerType.Ethernet别硬编码用e.Packet.LinkLayerType最稳。3.3 解析 IP 头与端口的关键字段IPPacket里几个字段值得盯SourceAddress、DestinationAddress是System.Net.IPAddress类型直接 ToString 就是点分十进制Protocol是枚举判断 TCP/UDP 用它TotalLength是 IP 包总长包含头。TCP 层里SourcePort、DestinationPort是 ushortPayloadData是 byte 数组应用层数据全在里面。UDP 层同理但PayloadData可能为 null取值前判空。如果要抓的是 Modbus TCP 这类应用协议端口过滤到 502 后tcp.PayloadData的前 7 个字节就是 MBAP 头第 8 字节开始是 PDU。这一步是「抓包」到「懂包」的分界线很多人卡在拿到字节不知道怎么切。4. 避坑与排查抓不到包时先看这五条4.1 现象设备列表为空代码报索引越界原因Npcap 未安装或安装时没勾选 WinPcap 兼容模式SharpPcap 找不到 wpcap.dll。解决重装 Npcap安装向导里明确勾选「Install Npcap in WinPcap API-compatible Mode」装完重启一次系统再跑。4.2 现象过滤器设了端口但一个包都收不到原因BPF 表达式写错比如把tcp port 502写成tcp port 502或者端口号超出 65535。解决先用device.Filter ip确认能收到任意 IP 包再逐步加端口条件表达式里不要加等号端口直接跟数字。4.3 现象能抓到包但 PayloadData 全是 null原因抓到的包是纯 ACK 或握手包本身没有应用层载荷或者链路层类型判断错导致解析偏移。解决先打印ipPacket.Protocol和tcp.PayloadData null判断握手包无载荷是正常的确认LinkLayerType用的是e.Packet.LinkLayerType而非硬编码。4.4 现象抓包程序 CPU 占用飙到 100%原因ReadTimeout设得太小或者回调里做了耗时操作比如写文件、发网络请求。解决ReadTimeout调到 5001000 毫秒回调里只做轻量解析把数据丢进ConcurrentQueue另起线程消费。4.5 现象混杂模式下抓到大量无关广播包原因混杂模式会收所有经过网卡的帧包括 ARP、DHCP 广播。解决过滤器里加and not broadcast and not multicast或者用ip host 目标IP限定通信对端把噪声挡在驱动层。5. 进阶把抓到的包落盘并做端口级统计5.1 用 Pcap 格式存盘方便二次分析抓到的包如果只打印就浪费了SharpPcap 支持直接写 pcap 文件Wireshark 能打开// 打开一个 pcap 写入器格式为标准 pcap var writer new CaptureFileWriterDevice(capture.pcap); device.OnPacketArrival (sender, e) { writer.Write(e.Packet); // 原始帧直接落盘 };CaptureFileWriterDevice的构造参数是文件路径写入的是原始链路层帧所以 Wireshark 打开后协议解析完全正常。注意 writer 要在 device 打开之后再创建关闭顺序是先停抓包、再关 writer、最后关 device顺序反了会丢最后几个包。5.2 按端口做收发字节统计现场排查经常要回答「这个端口到底跑了多少数据」用字典累加即可// 用线程安全字典按端口累计收发字节 var stats new ConcurrentDictionaryint, long(); device.OnPacketArrival (sender, e) { var raw Packet.ParsePacket(e.Packet.LinkLayerType, e.Packet.Data); var ip raw.ExtractIPPacket(); if (ip null) return; var tcp ip.ExtractTcpPacket(); if (tcp ! null) { // 按目的端口累加载荷长度 stats.AddOrUpdate(tcp.DestinationPort, tcp.PayloadData?.Length ?? 0, (k, v) v (tcp.PayloadData?.Length ?? 0)); } };ConcurrentDictionary的AddOrUpdate保证多线程回调下计数不丢。统计的是载荷长度而非帧长因为排查应用层流量时载荷更有意义。跑一段时间后遍历stats就能看到哪个端口最忙配合时间窗口还能算吞吐。5.3 一个我常犯的错早期我总在回调里直接Console.WriteLine抓高速流量时控制台成了瓶颈包丢得比抓的多。后来改成回调只入队、单独线程格式化输出丢包率立刻降下来。从那以后我每次写抓包工具都强制把「收包」和「处理」拆成两个线程这个习惯帮我省了无数次现场排查的返工。希望帮到你。本文还有配套的精品资源点击获取