C#如何读取和分析网络数据包捕获PCAP文件

来源:Golang编程网作者:天穹小白头衔:草根站长
导读:本期聚焦于小伙伴创作的《C#如何读取和分析网络数据包捕获PCAP文件》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《C#如何读取和分析网络数据包捕获PCAP文件》有用,将其分享出去将是对创作者最好的鼓励。

在网络开发场景中,PCAP文件是存储网络数据包捕获结果的通用格式,很多网络分析工具都会生成这类文件。如果需要在C#程序中读取和分析PCAP文件,首先要理解PCAP文件的二进制存储结构,再按照规范逐段解析数据。

C#如何读取和分析网络数据包捕获PCAP文件

PCAP文件基础结构

PCAP文件整体分为两部分,第一部分是全局的文件头,第二部分是多个连续的数据包记录。每个数据包记录又包含自身的数据包头和数据包实际内容。

全局文件头结构

PCAP全局文件头固定占24字节,各字段含义如下:

字段名字节长度说明
Magic Number4字节标识文件类型,小端模式下为0xa1b2c3d4
Major Version2字节主版本号,通常为2
Minor Version2字节次版本号,通常为4
This Zone4字节时区偏移,通常为0
Sig Figs4字节精确时间戳,通常为0
Snap Length4字节最大捕获数据包长度
Link Type4字节链路层类型,1代表以太网

数据包记录结构

每个数据包记录由16字节的数据包头和不定长的数据包内容组成,数据包头字段如下:

  • 时间戳秒数:4字节,数据包捕获的秒级时间戳
  • 时间戳微秒数:4字节,数据包捕获的微秒级偏移
  • 捕获长度:4字节,实际捕获到的数据包长度
  • 原始长度:4字节,数据包在链路上的原始长度

C#解析PCAP文件的实现步骤

1. 读取全局文件头

首先打开PCAP文件,读取前24字节解析全局文件头,验证文件合法性:

using System;
using System.IO;

public class PcapGlobalHeader
{
    public uint MagicNumber { get; set; }
    public ushort MajorVersion { get; set; }
    public ushort MinorVersion { get; set; }
    public uint SnapLength { get; set; }
    public uint LinkType { get; set; }
}

public class PcapParser
{
    public PcapGlobalHeader ReadGlobalHeader(string filePath)
    {
        using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
        using (BinaryReader br = new BinaryReader(fs))
        {
            PcapGlobalHeader header = new PcapGlobalHeader();
            header.MagicNumber = br.ReadUInt32();
            // 验证Magic Number,小端模式下的标准值
            if (header.MagicNumber != 0xa1b2c3d4)
            {
                throw new InvalidDataException("不是合法的PCAP文件");
            }
            header.MajorVersion = br.ReadUInt16();
            header.MinorVersion = br.ReadUInt16();
            br.ReadUInt32(); // 跳过This Zone字段
            br.ReadUInt32(); // 跳过Sig Figs字段
            header.SnapLength = br.ReadUInt32();
            header.LinkType = br.ReadUInt32();
            return header;
        }
    }
}

2. 读取数据包记录

读取完全局头之后,循环读取后续的数据包记录,直到文件结束:

public class PcapPacketHeader
{
    public uint TimestampSeconds { get; set; }
    public uint TimestampMicroseconds { get; set; }
    public uint CapturedLength { get; set; }
    public uint OriginalLength { get; set; }
}

public class PcapPacket
{
    public PcapPacketHeader Header { get; set; }
    public byte[] Data { get; set; }
}

public List<PcapPacket> ReadAllPackets(string filePath)
{
    List<PcapPacket> packets = new List<PcapPacket>();
    using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read))
    using (BinaryReader br = new BinaryReader(fs))
    {
        // 先跳过全局头24字节
        br.ReadBytes(24);
        while (fs.Position < fs.Length)
        {
            PcapPacket packet = new PcapPacket();
            PcapPacketHeader pktHeader = new PcapPacketHeader();
            // 读取数据包头16字节
            pktHeader.TimestampSeconds = br.ReadUInt32();
            pktHeader.TimestampMicroseconds = br.ReadUInt32();
            pktHeader.CapturedLength = br.ReadUInt32();
            pktHeader.OriginalLength = br.ReadUInt32();
            packet.Header = pktHeader;
            // 读取数据包内容
            packet.Data = br.ReadBytes((int)pktHeader.CapturedLength);
            packets.Add(packet);
        }
    }
    return packets;
}

3. 解析链路层数据

如果链路层类型为以太网(LinkType=1),可以进一步解析以太网帧:

public class EthernetFrame
{
    public byte[] DestinationMac { get; set; }
    public byte[] SourceMac { get; set; }
    public ushort EtherType { get; set; }
    public byte[] Payload { get; set; }
}

public EthernetFrame ParseEthernetFrame(byte[] data)
{
    if (data.Length < 14)
    {
        return null;
    }
    EthernetFrame frame = new EthernetFrame();
    frame.DestinationMac = new byte[6];
    Array.Copy(data, 0, frame.DestinationMac, 0, 6);
    frame.SourceMac = new byte[6];
    Array.Copy(data, 6, frame.SourceMac, 0, 6);
    frame.EtherType = (ushort)((data[12] << 8) | data[13]);
    frame.Payload = new byte[data.Length - 14];
    Array.Copy(data, 14, frame.Payload, 0, frame.Payload.Length);
    return frame;
}

使用示例

将上述逻辑组合起来,即可实现PCAP文件的读取和基础分析:

class Program
{
    static void Main(string[] args)
    {
        string pcapPath = "test.pcap";
        try
        {
            PcapParser parser = new PcapParser();
            var globalHeader = parser.ReadGlobalHeader(pcapPath);
            Console.WriteLine($"PCAP版本:{globalHeader.MajorVersion}.{globalHeader.MinorVersion}");
            Console.WriteLine($"链路层类型:{globalHeader.LinkType}");
            var packets = parser.ReadAllPackets(pcapPath);
            Console.WriteLine($"共解析到{packets.Count}个数据包");
            foreach (var pkt in packets)
            {
                DateTime timestamp = new DateTime(1970, 1, 1).AddSeconds(pkt.Header.TimestampSeconds).AddMilliseconds(pkt.Header.TimestampMicroseconds / 1000);
                Console.WriteLine($"数据包时间:{timestamp}, 长度:{pkt.Header.CapturedLength}");
                var ethFrame = ParseEthernetFrame(pkt.Data);
                if (ethFrame != null)
                {
                    Console.WriteLine($"源MAC:{BitConverter.ToString(ethFrame.SourceMac)},目的MAC:{BitConverter.ToString(ethFrame.DestinationMac)}");
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"解析失败:{ex.Message}");
        }
    }
}

注意事项

实际使用中需要注意几个问题,首先是字节序问题,PCAP文件默认使用小端字节序,解析时要确保BinaryReader的小端读取逻辑正确。其次是大文件场景,如果PCAP文件体积较大,不要一次性将所有数据包加载到内存,可以采用流式读取的方式逐个处理。最后是链路层类型兼容,不同抓包场景可能使用不同的链路层类型,需要根据LinkType字段调整解析逻辑。

C#PCAP文件解析网络数据包捕获packet_analysis修改时间:2026-07-15 11:27:38

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。