网络数据包监视 类

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;

namespace 网络数据包监视
{
    public class PacketArrivedEventArgs
    {
        public uint HeaderLength;  // = (uint)(head->ip_verlen & 0x0F) << 2;
        public string Protocol;    // = "ICMP"; break;
        public string IPVersion;   //= temp_version.ToString();
        public string DestinationAddress;  // = temp_ip.ToString();
        public string OriginationPort; // = IPAddress.NetworkToHostOrder(temp_srcport).ToString();
        public string DestinationPort; // = IPAddress.NetworkToHostOrder(temp_dstport).ToString();
        public uint PacketLength;  // = (uint)len;
        public uint MessageLength; // = (uint)len - e.HeaderLength;
        public byte[] ReceiveBuffer;   // = buf;
        public byte[] IPHeaderBuffer;
        public string OriginationAddress;
        public byte[] MessageBuffer;

        public PacketArrivedEventArgs()
        {
        }
    }

    public delegate void ReceiveData (byte[] receive_buf_bytes, int received_bytes);

    public class RowSocket
    {
        //事件句柄:包到达时引发事件
        public event PacketArrivedEventHandler OnPacketArrival;//声明时间句柄函数

        public RowSocket() //构造函数
        {
            error_occurred = false;
            len_receive_buf = 4096;
            receive_buf_bytes = new byte[len_receive_buf];
        }

        [StructLayout(LayoutKind.Explicit)]
        public struct IPHeader
        {
            [FieldOffset(0)]
            public byte ip_verlen; //I4位首部长度+4位IP版本号
            [FieldOffset(1)]
            public byte ip_tos; //8位服务类型TOS
            [FieldOffset(2)]
            public ushort ip_totallength; //16位数据包总长度(字节)
            [FieldOffset(4)]
            public ushort ip_id; //16位标识
            [FieldOffset(6)]
            public ushort ip_offset; //3位标志位
            [FieldOffset(8)]
            public byte ip_ttl; //8位生存时间 TTL
            [FieldOffset(9)]
            public byte ip_protocol; //8位协议(TCP, UDP, ICMP, Etc.)
            [FieldOffset(10)]
            public ushort ip_checksum; //16位IP首部校验和
            [FieldOffset(12)]
            public uint ip_srcaddr; //32位源IP地址
            [FieldOffset(16)]
            public uint ip_destaddr; //32位目的IP地址
        }

        public ReceiveData OnDataArrived;//

        const int SIO_RCVALL = unchecked((int)0x98000001);//监听所有的数据包

        private bool error_occurred; //套接字在接收包时是否产生错误
        public bool KeepRunning; //是否继续进行
        private static int len_receive_buf; //得到的数据流的长度
        byte[] receive_buf_bytes; //收到的字节
        private Socket socket = null; //声明套接字

        public void CreateAndBindSocket(string IP) //建立并绑定套接字
        {
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Raw, ProtocolType.IP);
            socket.Blocking = false; //置socket非阻塞状态
            socket.Bind(new IPEndPoint(IPAddress.Parse(IP), 0)); //绑定套接字

            if (SetSocketOption() == false) error_occurred = true;
        }

        private bool SetSocketOption() //设置raw socket
        {
            bool ret_value = true;
            try
            {
                socket.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.HeaderIncluded, 1);
                byte[] IN = new byte[4] { 1, 0, 0, 0 };
                byte[] OUT = new byte[4];

                //低级别操作模式,接受所有的数据包,这一步是关键,必须把socket设成raw和IP Level才可用SIO_RCVALL
                int ret_code = socket.IOControl(SIO_RCVALL, IN, OUT);
                ret_code = OUT[0] + OUT[1] + OUT[2] + OUT[3];//把4个8位字节合成一个32位整数
                if (ret_code != 0) ret_value = false;
            }
            catch (SocketException)
            {
                ret_value = false;
            }
            return ret_value;
        }

        /*
        int WSAIoctl(
        SOCKET s, //一个指定的套接字
        DWORD dwIoControlCode, //控制操作码
        LPVOID lpvInBuffer, //指向输入数据流的指针
        DWORD cbInBuffer, //输入数据流的大小(字节数)
        LPVOID lpvOutBuffer, // 指向输出数据流的指针
        DWORD cbOutBuffer, //输出数据流的大小(字节数)
        LPDWORD lpcbBytesReturned, //指向输出字节流数目的实数值
        LPWSAOVERLAPPED lpOverlapped, //指向一个WSAOVERLAPPED结构
        LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine//指向操作完成时执行的例程
        );        
         */

        public bool ErrorOccurred
        {
            get
            {
                return error_occurred;
            }
        }

       
        //解析接收的数据包,形成PacketArrivedEventArgs事件数据类对象,并引发PacketArrival事件
        unsafe private void Receive(byte[] buf, int len)
        {
            byte temp_protocol = 0;
            uint temp_version = 0;
            uint temp_ip_srcaddr = 0;
            uint temp_ip_destaddr = 0;
            short temp_srcport = 0;
            short temp_dstport = 0;
            IPAddress temp_ip;

            PacketArrivedEventArgs e = new PacketArrivedEventArgs();//新网络数据包信息事件

            fixed (byte* fixed_buf = buf)
            {
                IPHeader* head = (IPHeader*)fixed_buf;//把数据流整和为IPHeader结构
                e.HeaderLength = (uint)(head->ip_verlen & 0x0F) << 2;

                temp_protocol = head->ip_protocol;
                switch (temp_protocol)//提取协议类型
                {
                    case 1: e.Protocol = "ICMP"; break;
                    case 2: e.Protocol = "IGMP"; break;
                    case 6: e.Protocol = "TCP"; break;
                    case 17: e.Protocol = "UDP"; break;
                    default: e.Protocol = "UNKNOWN"; break;
                }

                temp_version = (uint)(head->ip_verlen & 0xF0) >> 4;//提取IP协议版本
                e.IPVersion = temp_version.ToString();

                //以下语句提取出了PacketArrivedEventArgs对象中的其他参数
                temp_ip_srcaddr = head->ip_srcaddr;
                temp_ip_destaddr = head->ip_destaddr;
                temp_ip = new IPAddress(temp_ip_srcaddr);
                e.OriginationAddress = temp_ip.ToString();
                temp_ip = new IPAddress(temp_ip_destaddr);
                e.DestinationAddress = temp_ip.ToString();

                temp_srcport = *(short*)&fixed_buf[e.HeaderLength];
                temp_dstport = *(short*)&fixed_buf[e.HeaderLength + 2];
                e.OriginationPort = IPAddress.NetworkToHostOrder(temp_srcport).ToString();
                e.DestinationPort = IPAddress.NetworkToHostOrder(temp_dstport).ToString();

                e.PacketLength = (uint)len;
                e.MessageLength = (uint)len - e.HeaderLength;

                e.ReceiveBuffer = buf;

                e.IPHeaderBuffer = new byte[e.HeaderLength];
                //把buf中的IP头赋给PacketArrivedEventArgs中的IPHeaderBuffer
                Array.Copy(buf, 0, e.IPHeaderBuffer, 0, (int)e.HeaderLength);

                //把buf中的包中内容赋给PacketArrivedEventArgs中的MessageBuffer
                e.MessageBuffer = new byte[e.MessageLength];
                Array.Copy(buf, (int)e.HeaderLength, e.MessageBuffer, 0, (int)e.MessageLength);
            }
            //引发PacketArrival事件
            if (OnPacketArrival != null)
                OnPacketArrival(this, e);
        }
       
        public void Run() //开始监听
        {
            IAsyncResult ar = socket.BeginReceive(receive_buf_bytes, 0, len_receive_buf, SocketFlags.None, new AsyncCallback(CallReceive), this);
        }

        private void CallReceive(IAsyncResult ar)//异步回调
        {
            int received_bytes;
            received_bytes = socket.EndReceive(ar);
            Receive(receive_buf_bytes, received_bytes);
            //OnPacketArrival(e);
            //OnDataArrived(receive_buf_bytes, received_bytes);

            if (KeepRunning) Run();
        }

        public delegate void PacketArrivedEventHandler(Object sender, PacketArrivedEventArgs args);

        public void Close() //关闭raw socket
        {
            if (socket != null)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }
        }
    }
}

用法:

   RowSocket rs;

            rs = new RowSocket();
            rs.OnPacketArrival += new RowSocket.PacketArrivedEventHandler(rs_OnPacketArrival);
            rs.CreateAndBindSocket("10.32.32.52");
            rs.KeepRunning = true;
            rs.Run();

更多黄瑞杰的文章

原文地址:https://www.cnblogs.com/chrishwang/p/1109264.html