zoukankan      html  css  js  c++  java
  • 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>(); //待处理数据包队列
    
    
        }
    
    }
    
  • 相关阅读:
    心理分析:爱挑刺的人是什么心理
    推荐几个最好用的CRM软件,本人亲测
    Xamarin安装和跳坑指南
    一个简单的游戏开发框架(七.动作Motion)
    一个简单的游戏开发框架(六.行为Action)
    一个简单的游戏开发框架(五.对象Object)
    一个简单的游戏开发框架(四.舞台Stage)
    一个简单的游戏开发框架(三.事件管理)
    一个简单的游戏开发框架(二.对外接口)
    一个简单的游戏开发框架(一.框架的意义)
  • 原文地址:https://www.cnblogs.com/kinyer/p/2595283.html
Copyright © 2011-2022 走看看