SharpPcap 3.4使用范例

 

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using SharpPcap;





namespace TestConsole

{

    class Program

    {

        static void Main(string[] args)

        {

            //显示SharpPcap版本

            string ver = SharpPcap.Version.VersionString;

            Console.WriteLine("SharpPcap {0}", ver);



            //获取网络设备

            var devices = LivePcapDeviceList.Instance;

            if (devices.Count < 1)

            {

                Console.WriteLine("找不到网络设备");

                return;

            }



            Console.WriteLine();

            Console.WriteLine("以下是目前本计算机上的活动网络设备:");

            Console.WriteLine("----------------------------------------------------");

            Console.WriteLine();



            int i = 0;

            foreach (LivePcapDevice dev in devices)

            {

                Console.WriteLine("{0}) {1} {2}", i, dev.Name, dev.Description);

                i++;

            }



            //选择要监听的网络设备



            Console.WriteLine();

            Console.Write("-- 请选择一个需要监听的网络设备: ");

            i = int.Parse(Console.ReadLine());

            LivePcapDevice device = devices[i];







            Console.Write("-- 请选择操作:监听通讯[C/c],多线程监听通讯[T/t],监听统计[F/f],发送随机数据包[S/s]? ");

            string resp = Console.ReadLine().ToUpper();



            while (!(resp.StartsWith("C") || resp.StartsWith("F") || resp.StartsWith("T") || resp.StartsWith("S")))

            {

                resp = Console.ReadLine().ToUpper();

            }



            try

            {

                if (resp.StartsWith("C") || resp.StartsWith("F") || resp.StartsWith("T"))

                {

                    //监听过滤条件

                    //string filter = "ip and tcp";



                    //连接设备

                    System.Threading.Thread backgroundThread = null;

                    

                    int readTimeoutMilliseconds = 1000;

                    if (resp.StartsWith("F"))

                    {

                        device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

                        //device.SetFilter(filter);

                        device.Mode = CaptureMode.Statistics; //抓包统计

                        device.OnPcapStatistics += new StatisticsModeEventHandler(device_OnPcapStatistics); //抓包统计回调事件



                    }



                    else if (resp.StartsWith("C"))

                    {

                        device.Open(DeviceMode.Promiscuous, readTimeoutMilliseconds);

                        //device.SetFilter(filter);

                        device.Mode = CaptureMode.Packets; //抓数据包

                        showDetails = resp.EndsWith("-A"); //当抓数据包时,检查是否要查看详情



                        device.OnPacketArrival += new PacketArrivalEventHandler(device_OnPacketArrival); //抓数据包回调事件



                    }



                    else

                    {

                        backgroundThread = new System.Threading.Thread(BackgroundThread);

                        backgroundThread.Start();

                        device.Open();

                       // device.SetFilter(filter);

                        device.Mode = CaptureMode.Packets; //抓数据包

                        showDetails = resp.EndsWith("-A"); //当抓数据包时,检查是否要查看详情

                        device.OnPacketArrival += new PacketArrivalEventHandler(device_OnThreadPacketArrival); //抓数据包回调事件

                    }







                    Console.WriteLine();

                    //Console.WriteLine("-- 当前TCPdump过滤条件: \"{0}\"", filter);

                    Console.WriteLine("-- 正在监听设备 {0}, 按 '回车' 键以停止监听...", device.Description);





                    //开始监听

                    device.StartCapture();



                    //停止监听

                    Console.ReadLine();

                    device.StopCapture();

                    Console.WriteLine("-- 停止监听.");

                    if (backgroundThread != null)

                    {

                        BackgroundThreadStop = true;

                        backgroundThread.Join();

                    }

                }

                else if (resp.StartsWith("S"))

                {

                    //连接设备

                    device.Open();

                    //生成随机数据包

                    byte[] bytes = GetRandomPacket();

                    try

                    {



                        //发送数据

                        device.SendPacket(bytes);

                        SendQueue squeue = new SendQueue(2000);

                        Console.WriteLine("-- 单个数据包发送成功.");



                        for (int j = 0; j < 10; j++)

                        {

                            if (!squeue.Add(bytes))

                            {

                                Console.WriteLine("-- 警告: 队列大小不足以存放所有数据包,将只发送部分数据包.");

                                break;

                            }

                        }

                        device.SendQueue(squeue, SendQueueTransmitModes.Synchronized);

                        Console.WriteLine("-- 数据包队列发送完毕.");

                    }



                    catch (Exception e)

                    {

                        Console.WriteLine("-- " + e.Message);

                    }



                }



            }

            catch (Exception e)

            {

                Console.WriteLine("-- " + e.Message);

            }



            finally

            {

                if (device.Opened)

                {



                    //断开设备连接



                    Console.WriteLine(device.Statistics().ToString());



                    device.Close();



                    Console.WriteLine("-- 断开设备连接.");



                    Console.Write("按 '回车' 键以退出...");



                    Console.Read();



                }



            }



        }







        static bool showDetails = false; //查看详情的参数



        /// <summary>



        /// 抓包方法



        /// </summary>



        private static void device_OnPacketArrival(object sender, CaptureEventArgs e)

        {



            PcapPorcessContext(e.Packet);



        }







        private static void PcapPorcessContext(PacketDotNet.RawPacket pPacket)

        {



            var time = pPacket.Timeval.Date;

            var len = pPacket.Data.Length;

            var layer = pPacket.LinkLayerType;

            Console.WriteLine("{0}:{1}:{2},{3} Len={4} Layer={5}",

                    time.Hour, time.Minute, time.Second, time.Millisecond, len, layer);





            var packet = PacketDotNet.Packet.ParsePacket(pPacket); //Raw基础包对象

            if (layer == PacketDotNet.LinkLayers.Ethernet) //以太网包

            {

                var ethernetPacket = (PacketDotNet.EthernetPacket)packet;

                System.Net.NetworkInformation.PhysicalAddress srcMac = ethernetPacket.SourceHwAddress;

                System.Net.NetworkInformation.PhysicalAddress destMac = ethernetPacket.DestinationHwAddress;

                Console.WriteLine("MAC:{0} -> {1}", srcMac, destMac);

                if (showDetails) Console.WriteLine("Ethernet packet: " + ethernetPacket.ToColoredString(false));

            }



            var ipPacket = PacketDotNet.IpPacket.GetEncapsulated(packet);  //IP包

            if (ipPacket != null)

            {

                System.Net.IPAddress srcIp = ipPacket.SourceAddress;

                System.Net.IPAddress destIp = ipPacket.DestinationAddress;

                Console.WriteLine("IP: {0} -> {1}", srcIp, destIp);

                if (showDetails) Console.WriteLine("IP packet: " + ipPacket.ToColoredString(false));

                var tcpPacket = PacketDotNet.TcpPacket.GetEncapsulated(packet); //TCP包

                if (tcpPacket != null)

                {

                    int srcPort = tcpPacket.SourcePort;

                    int destPort = tcpPacket.DestinationPort;

                    Console.WriteLine("TCP Port: {0} -> {1}", srcPort, destPort);

                    if (showDetails) Console.WriteLine("TCP packet: " + tcpPacket.ToColoredString(false));

                }

                var udpPacket = PacketDotNet.UdpPacket.GetEncapsulated(packet); //UDP包

                if (udpPacket != null)

                {

                    int srcPort = udpPacket.SourcePort;

                    int destPort = udpPacket.DestinationPort;

                    Console.WriteLine("UDP Port: {0} -> {1}", srcPort, destPort);

                    if (showDetails) Console.WriteLine("UDP packet: " + udpPacket.ToColoredString(false));

                }

            }



        }



        static ulong oldSec = 0;

        static ulong oldUsec = 0;



        /// <summary>

        /// 抓包统计方法

        /// </summary>

        private static void device_OnPcapStatistics(object sender, StatisticsModeEventArgs e)

        {



            // 计算统计心跳间隔

            ulong delay = (e.Statistics.Timeval.Seconds - oldSec) * 1000000 - oldUsec + e.Statistics.Timeval.MicroSeconds;



            // 获取 Bits per second

            ulong bps = ((ulong)e.Statistics.RecievedBytes * 8 * 1000000) / delay;

            /*                                       ^       ^



                                                     |       |



                                                     |       | 



                                                     |       |



                            converts bytes in bits --        |



                                                             |



                        delay is expressed in microseconds --



            */







            // 获取 Packets per second

            ulong pps = ((ulong)e.Statistics.RecievedPackets * 1000000) / delay;



            // 将时间戳装换为易读格式

            var ts = e.Statistics.Timeval.Date.ToLongTimeString();







            // 输出统计结果

            Console.WriteLine("{0}: bps={1}, pps={2}", ts, bps, pps);







            //记录本次统计时间戳,以用于下次统计计算心跳间隔



            oldSec = e.Statistics.Timeval.Seconds;



            oldUsec = e.Statistics.Timeval.MicroSeconds;



        }





        /// <summary>



        /// 生成一个大小为200的随机数据包



        /// </summary>

        private static byte[] GetRandomPacket()

        {



            byte[] packet = new byte[200];



            Random rand = new Random();



            rand.NextBytes(packet);



            return packet;



        }



        /// <summary>



        /// 生成一个大小为98的数据包



        /// </summary>

        private static byte[] GetPacket()

        {



            byte[] packet = new byte[]



            {



                0x00,0x02,0x65,0x11,0xa6,0x05,                     //srcMac



                0x00,0x1b,0x38,0xa5,0xc2,0x40,                     //destMac



                0x08,0x00,                                         //Type Ip



                0x45,                                              //Version 4



                0x00,                                              //Differentiated Services Field 分隔符



                0x00,0x54,                                         //Total Length 84



                0x43,0x08,                                         //Identification 校验位



                0x40,0x00,                                         //Fragment offset 片偏移



                0x80,                                              //Time to live 生存时间



                0x06,                                              //Protocol TCP



                0x40,0x00,                                         //Header checksum 报头校验和



                0xc0,0xa8,0x00,0x71,                               //srcIP



                0xc0,0xa8,0x00,0x6a,                               //destIP



                0x26,0x8e,                                         //srcPort



                0x04,0x04,                                         //destPort



                0x5b,0x0c,0x5e,0xc7,                               //Sequence number 序号



                0xca,0xf9,0x1b,0xb1,                               //Acknowledgement number 应答号



                0x80,                                              //Header Length 32



                0x18,                                              //Flags [PSH,ACK]



                0x41,0x10,                                         //Window size



                0x82,0x72,                                         //Checksum 校验和



                0x01,                                              //Options NOP



                0x01,                                              //Options NOP



                0x08,0x0a,0x00,0x00,0xac,0x4c,0x00,0x41,0x50,0xaa, //Options Timestamps



                0x21,                                              //Data Start 这之后是我这个项目中的服务器和终端通讯的特有的附加数据



                0x0a,                                              //Command



                0x00,0x00,                                         //CID



                0x01,0x00,0x00,0x00,                               //TID



                0x00,0x00,0x00,0x00,                               //Param1



                0x00,0x00,0x00,0x00,                               //Param2



                0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,           //Param3



                0x30,0x30,0x30,0x30,                               //ErrorCode



                0x00,0x00,0xec,0x00                                //ExtraData



            };



            return packet;



        }



        private static DateTime LastStatisticsOutput = DateTime.Now;

        private static TimeSpan LastStatisticsInterval = new TimeSpan(0, 0, 2);

        private static void device_OnThreadPacketArrival(object sender, CaptureEventArgs e)

        {



            //输出设备通讯统计信息



            var Now = DateTime.Now;



            var interval = Now - LastStatisticsOutput;



            if (interval > LastStatisticsInterval)

            {



                Console.WriteLine("Device Statistics: " + ((LivePcapDevice)e.Device).Statistics());



                LastStatisticsOutput = Now;



            }







            lock (QueueLock)

            {



                PacketQueue.Add(e.Packet); //将捕获到的数据包加入处理队列



            }



        }



        /// <summary>



        /// 多线程处理数据包队列



        /// </summary>

        private static void BackgroundThread()

        {



            while (!BackgroundThreadStop)

            {



                bool shouldSleep = true;







                lock (QueueLock)

                {



                    if (PacketQueue.Count != 0)

                    {



                        shouldSleep = false;



                    }



                }







                if (shouldSleep)

                {



                    System.Threading.Thread.Sleep(250);



                }



                else //处理队列

                {



                    List<PacketDotNet.RawPacket> ourQueue; //本线程待处理队列



                    lock (QueueLock)

                    {



                        ourQueue = PacketQueue;



                        PacketQueue = new List<PacketDotNet.RawPacket>();



                    }







                    Console.WriteLine("BackgroundThread: Local Queue Count is {0}", ourQueue.Count);







                    foreach (var packet in ourQueue)

                    {



                        PcapPorcessContext(packet);



                    }



                }



            }



        }

        private static bool BackgroundThreadStop = false; //线程停止标识

        private static object QueueLock = new object(); //线程锁变量

        private static List<PacketDotNet.RawPacket> PacketQueue = new List<PacketDotNet.RawPacket>(); //待处理数据包队列





    }



}

 

你可能感兴趣的:(sha)