Sniffer的完整代码,基于winpcap抓包统计吞吐量

using System;
using System.Net;
using System.Net.Sockets;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Collections.Concurrent;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using SharpPcap;
using SharpPcap.WinPcap;
using PacketDotNet;
using Demo.STP.Sniff.Packets;

namespace Demo.STP.Sniff
{
    /// <summary>
    /// 嗅探器,提供原始数据源
    /// </summary>
    public sealed class Sniffer
    {
        #region Instance
        private static readonly Lazy<Sniffer> _lazy =
            new Lazy<Sniffer>(() => new Sniffer());

        public static Sniffer Instance
        {
            get { return _lazy.Value; }
        }

        private Sniffer() { }
        #endregion Instance

        #region Init
        /// <summary>
        /// 初始化嗅探器
        /// </summary>
        /// <param name="ipAddress">需拦截网卡所配IP</param>
        /// <param name="filter">数据包过滤规则</param>
        public void Init(string ipAddress, string filter = "")
        {
            var network = Demo.STP.Common.NetHelper.GetNetwork(ipAddress);
            if (network == null)
                throw new ArgumentException(string.Format("Invalid IPAddress {0}.", ipAddress));

            this._currentDevice = WinPcapDeviceList.Instance.Where(deviceItem =>
                string.Equals(network.Name, deviceItem.Interface.FriendlyName, StringComparison.OrdinalIgnoreCase))
                .FirstOrDefault();

            if (this._currentDevice == null)
                throw new ArgumentException("无法从WinPcap找到对应网卡.");

            this._currentDevice.OnPacketArrival += device_OnPacketArrival;
            this._currentDevice.Open(DeviceMode.Normal);
            this._currentDevice.Filter = filter;
        }

        private void device_OnPacketArrival(object sender, CaptureEventArgs e)
        {
            this._packetQueue.Enqueue(e.Packet);
        }
        #endregion Init

        #region Start Hook
        /// <summary>
        /// 启动嗅探器
        /// </summary>
        public void StartHook()
        {
            if (this._currentDevice == null)
                throw new ArgumentException("请先初始化嗅探器.");

            KeepHook = true;
            this._currentDevice.StartCapture();

            RawCapture rawCapture = null;

            Task.Factory.StartNew(() =>
            {
                while (KeepHook)
                {
                    if (this._packetQueue.IsEmpty)
                    {
                        //理论上能轻松应对所有终端
                        //如果吞吐量达不到要求,请删除Sleep,但会占用一个核心的全部时间
                        Thread.Sleep(10);
                        continue;
                    }
                    if (this._packetQueue.TryDequeue(out rawCapture))
                    {
                        var basePacket = this.AnalysisPacket(rawCapture);
                        if (basePacket.HasValue)
                        {
                            OnPacketArrival(new PacketArrivedEventArgs { BasePacket = basePacket.Value });
                        }
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }
        #endregion Start Hook

        #region Stop Hook
        /// <summary>
        /// 停止嗅探器
        /// </summary>
        public void StopHook()
        {
            if (this._currentDevice == null) return;

            KeepHook = false;

            if (this._currentDevice.Started)
                this._currentDevice.StopCapture();

            this._currentDevice.OnPacketArrival -= device_OnPacketArrival;
            this._currentDevice.Close();
        }
        #endregion Stop Hook

        #region 解析数据包
        private Nullable<IPBasePacket> AnalysisPacket(RawCapture rawCapture)
        {
            try
            {
                var rawPacket = rawCapture.ParseRawPacket();
                var ipPacket = rawPacket.ExtractTragetPacket<IpPacket>();
                if (ipPacket == null)
                    return null;

                EnumIPProtocol targetProtocol;
                var parseFlag = Enum.TryParse(ipPacket.Protocol.ToString(), true, out targetProtocol);
                if (!parseFlag)
                    return null;

                IPBasePacket basePacket = new IPBasePacket();
                basePacket.Protocol = targetProtocol;
                basePacket.IPVersion = ipPacket.Version.ToString();
                basePacket.SourceIP = ipPacket.SourceAddress.ToString();
                basePacket.TargetIP = ipPacket.DestinationAddress.ToString();

                dynamic tcp_udp_Packet = rawPacket.ExtractTragetPacket<TcpPacket>();
                if (tcp_udp_Packet == null)
                    tcp_udp_Packet = rawPacket.ExtractTragetPacket<UdpPacket>();

                if (tcp_udp_Packet != null)
                {
                    if (tcp_udp_Packet.PayloadData == null)
                        return null; 

                    basePacket.SourcePort = tcp_udp_Packet.SourcePort;
                    basePacket.TargetPort = tcp_udp_Packet.DestinationPort;

                    //basePacket.PacketLength = (uint)tcp_udp_Packet.Bytes.Length;
                    //basePacket.HeaderLength = (uint)tcp_udp_Packet.Header.Length;
                    //basePacket.MessageLength = (uint)tcp_udp_Packet.PayloadData.Length;

                    //basePacket.PacketBuffer = tcp_udp_Packet.Bytes;
                    //basePacket.HeaderBuffer = tcp_udp_Packet.Header;
                    //basePacket.MessageBuffer = tcp_udp_Packet.PayloadData;

                    basePacket.MessageLength = (uint)tcp_udp_Packet.PayloadData.Length;
                    basePacket.MessageBuffer = tcp_udp_Packet.PayloadData;
                }

                return basePacket;
            }
            catch
            {
                return null;
            }
        }
        #endregion 解析数据包

        #region PacketArrival Event
        public event EventHandler<PacketArrivedEventArgs> PacketArrival;

        internal void OnPacketArrival(PacketArrivedEventArgs e)
        {
            if (PacketArrival != null)
            {
                PacketArrival(this, e);
            }
        }

        public bool IsMonitorEmpty
        {
            get { return PacketArrival == null; }
        }
        #endregion PacketArrival Event

        #region Fields & Propertys
        public bool KeepHook { get; private set; }
        private WinPcapDevice _currentDevice;
        private ConcurrentQueue<RawCapture> _packetQueue = new ConcurrentQueue<RawCapture>();
        #endregion Fields & Propertys
    }

    public class PacketArrivedEventArgs : EventArgs
    {
        public IPBasePacket BasePacket { get; set; }
    }
}
时间: 2024-11-05 02:22:08

Sniffer的完整代码,基于winpcap抓包统计吞吐量的相关文章

winpcap抓包原理

winpcap抓包原理 WinPcap 是由伯克利分组捕获库派生而来的分组捕获库,它是在Windows 操作平台上来实现对底层包的截取过滤.WinPcap 是 BPF 模型和 Libpcap 函数库在 Windows 平台下网络数据包捕获和网络状态分析的一种体系结构,这个 体系结构是由一个核心的包过滤驱动程序,一个底层的动态连接库 Packet.dll 和一个高层的独立于系统的函数库 Libpcap 组成.底层的包 捕获驱动程序实际为一个协议网 络驱动程序,通过对 NDIS 中函数的调用为 Wi

基于wireshark抓包分析TCP的三次握手

在TCP/IP协议通讯过程中,采用三次握手建立连接,从而保证连接的安全可靠. 通常三次握手步骤如下: 1. 第1次握手:建立连接时,客户端发送 SYN 包到服务器端,携带一个序列码给服务器端用于确认,并进入 SYN_SEND 状态,等待服务器端确认.(发起连接状态) 2. 第2次握手:服务器端收到 SYN 包,首先确认客户的SYN,并对序列码加1处理,发送一个自己的SYN包,携带一个自己的序列码,即 SYN+ACK 包,此时服务器进入 SYN_RECV 状态.(连接接收状态) 3. 第3次握手:

NetAnalyzer笔记 之 三. 用C++做一个抓包程序

[创建时间:2015-08-27 22:15:17] NetAnalyzer下载地址 经过前两篇的瞎扯,你是不是已经厌倦了呢,那么这篇让我们来点有意思的吧,什么,用C#.不,这篇我们先来C++的 Winpcap开发环境配置 完成了对Winpcap的介绍,什么,你没看到Winpcap的介绍,左转,百度(其实,真的是不想复制).我们就需要做一点有用的事情,比如写一个简单的数据采集工具.当然在此之前,我们需要配置Winpcap的开发环境. (1) 运行环境设置 Win32 平台下Winpcap应用程序

https wireshark抓包——要解密出原始数据光有ssl 证书还不行,还要有浏览器内的pre-master-secret(内存里)

基于wireshark抓包的分析 首先使用wireshark并且打开浏览器,打开百度(百度使用的是HTTPS加密),随意输入关键词浏览. 我这里将抓到的包进行过滤.过滤规则如下 ip.addr == 115.239.210.27 && ssl 1 下面用图来描述一下上面抓包所看到的流程. 1. Client Hello 打开抓包的详细,如下. 不难看出,这一握手过程,客户端以明文形式传输了如下信息: 版本信息(TLS 1.2) 随机数 Session ID(用于加快握手过程,可参考TLS会

基于Linux C的socket抓包程序和Package分析 (一)

 测试运行平台:CentOS 6.5发行版,内核版本3.11 1. Linux抓包源程序 在OSI七层模型中,网卡工作在物理层和数据链路层的MAC子层. 进行网络通信时,源主机通过socket(或其它)应用程序产生IP报文,经过各个OSI层层封装,数据包以Ethernet帧的形式进入物理层.Ethernet帧包含源主机地址.IP报文.目标地址(IP地址.端口号或映射的6字节MAC地址)和需要传送到目标主机的其它信息. 目标的MAC地址是哪里来的呢?这牵扯到一个ARP协议(介乎于网络层和数据链

基于HTTP访问特定URL的抓包程序该怎么写

抓包是一个简单易行的事,它可以帮你分析网络的行为.我记得早在2004年的时候,老师就讲过抓包有多么重要.        作为程序员而言,除了抓包几乎没有任何手段探测网络行为,程序员没有机会触摸网络设备,也就没有能力洞悉网络细节,程序员唯一能触摸到的就是自己的终端,在这个终端上唯一能做的就是抓包.我是半个程序员,所以不管站在谁的立场上,我都认为抓包是一个重要的事,虽然在我内心看来,抓包和分析数据包解决不了大多数的问题....        在一台承载大量业务的机器上怎么抓包成了一个问题.因为虚拟主

用Wireshark抓包来揭开ftp client GG和ftp server MM的勾搭内容并用C代码来简要模拟实现Windows自带的ftp client

前面, 我们玩过http, 颇有点意思, 在本文中, 我们继续来玩ftp(file transfer protocol).   http和ftp都是建立在tcp之上的应用层协议, 无论他们怎么包装, 怎么装bigger, 最终还是基于tcp端到端传输的.本文主要分为两个部分: 一. 用Wireshark抓包来揭开ftp client GG和ftp server MM的勾搭内容.二.用C代码来简要模拟实现Windows自带的ftp client. 说明, 本文中的实验, 我用了两台电脑, 分别是p

WinPcap网络抓包分析程序--总结

应付大作业写的一个程序,先给出程序的运行界面 程序的核心内容是抓包然后分析数据,我做的最多的也是协议分析这块内容.上面首先给出的是当前网络的上传下载速度,这块内容我是参考Windows性能计数器来写的,就是PDH,直接获取相应的接口, 获取数据,这块内容直接放出代码 1 #include <Pdh.h> 2 #include <list> 3 #pragma comment(lib, "Pdh.lib") 4 5 class NetWorkSpeed 6 { 7

c语言基于Linux下用libpcap实现抓包程序

c语言基于libpcap实现一个抓包程序过程 基于pcap的嗅探器程序的总体架构,其流程如下:(1)首先要决定用哪一个接口进行嗅探开始.在Linux中,这可能是eth0,而在BSD系统中则可能是xl1等等.我们也可以用一个字符串来定义这个设备,或者采用pcap提供的接口名来工作.(... 基于pcap的嗅探器程序的总体架构,其流程如下: (1)首先要决定用哪一个接口进行嗅探开始.在Linux中,这可能是eth0,而在BSD系统中则可能是xl1等等.我们也可以用一个字符串来定义这个设备,或者采用p