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

来源:互联网 发布:微信群二维码采集软件 编辑:程序博客网 时间:2024/05/22 23:48
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; }    }}

 

0 0
原创粉丝点击