主页 > 编程资料 > C# >
发布时间:2015-09-26 作者:网络 阅读:187次

最近一项目中要求显示网络流量,而且必须使用C#。

事实上,调用 IpHlpApi.dll 的 GetIfTable API 可以轻易获得网络信息和网络流量。只是要在C#中实现还是比较复杂。

先看看怎么定义该 API
[DllImport("IpHlpApi.dll")]
        extern static public uint GetIfTable(byte[] pIfTable, ref uint pdwSize, bool bOrder);
本来想把 pIfTable 定义为 IntPtr,但是这样的结果是,获取的信息是错误的(直到现在都不知是什么原因)。

但显然定义为 byte[] 是不能直接使用的。幸好在 Google Code Search 找到了三个类:

CustomtMarshaler.cs
using System;
using System.IO;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;

namespace Lemony.SystemInfo
{
   
    /**////


    /// CustomMarshaler class implementation.
    ///

    public abstract class CustomMarshaler
    {
        Fields#region Fields
        // The internal buffer
        internal byte[] data;
        private MemoryStream stream;
        private BinaryReader binReader;
        private BinaryWriter binWriter;
       
        #endregion
   
        constructors#region constructors

        public CustomMarshaler()
        {

        }
       
        #endregion

        public methods#region public methods

        public void Deserialize()
        {
            if (data != null)
            {
                if (binReader != null)
                {
                    binReader.Close();
                    stream.Close();
                }
                // Create a steam from byte array
                stream = new MemoryStream(data);
                binReader = new BinaryReader(stream, System.Text.Encoding.Unicode);
                ReadFromStream(binReader);
                binReader.Close();
            }

        }

        public void Serialize()
        {
            if (data != null)
            {
                stream = new MemoryStream(data);
                binWriter = new BinaryWriter(stream, System.Text.Encoding.Unicode);
                WriteToStream(binWriter);
                binWriter.Close();
            }
        }

        public int GetSize()
        {   
            int size = 0;

            FieldInfo[] fields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);

            foreach (FieldInfo field in fields )
            {
                if (field.FieldType.IsArray)
                {
                    size += GetFieldSize(field);
                }
                else if (field.FieldType == typeof(string))
                {
                    size += GetFieldSize(field)*2;
                }
                else if (field.FieldType.IsPrimitive)
                {
                    size += Marshal.SizeOf(field.FieldType);
                }
            }

            return size;
        }

        #endregion

        properties#region properties

        public byte[] ByteArray
        {
            get
            {
                return data;
            }
        }

        #endregion

        virtual and protected methods#region virtual and protected methods

        public virtual void ReadFromStream(BinaryReader reader)
        {
            object[] param = null;

            // Get all public fields
            FieldInfo[] fields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
           
            // Loop through the fields
            foreach(FieldInfo field in fields)
            {
                // Retrieve the read method from ReadMethods hashtable
                MethodInfo method = (MethodInfo)MarshallingMethods.ReadMethods[field.FieldType];

                if (field.FieldType.IsArray)
                {
                    Type element = field.FieldType.GetElementType();
                    if (element.IsValueType && element.IsPrimitive)
                    {
                        if ((element == typeof(char)) || element == typeof(byte))
                        {                                                                                
                            param = new object[1];
                            param[0] = GetFieldSize(field);
                            field.SetValue(this, method.Invoke(reader, param));
                        }
                        else // any other value type array
                        {
                            param = new object[2];
                            param[0] = reader;
                            param[1] = GetFieldSize(field);
                            field.SetValue(this, method.Invoke(null, param));
                        }
                    }
                    else // array of sub structures
                    {
                        int size = GetFieldSize(field);
                        method = (MethodInfo)MarshallingMethods.ReadMethods[typeof(CustomMarshaler)];
                        Array objArray = Array.CreateInstance(element, size);
                        for(int i=0;i                        {
                            objArray.SetValue(Activator.CreateInstance(element), i);
                            method.Invoke(objArray.GetValue(i), new object[]{reader});
                        }
                        field.SetValue(this, objArray);
                    }
                }
                else if (field.FieldType == typeof(string))
                {   
                    param = new object[2];
                    param[0] = reader;
                    param[1] = GetFieldSize(field);
                    field.SetValue(this, method.Invoke(null, param));
                }
                else if (field.FieldType.IsValueType && field.FieldType.IsPrimitive)// regular value type
                {
                    field.SetValue(this, method.Invoke(reader, null));
                }
                else //process substructure
                {
                    CustomMarshaler subStruct = (CustomMarshaler)Activator.CreateInstance(field.FieldType);
                    subStruct.ReadFromStream(reader);
                }
            }
        }

        public virtual void WriteToStream(BinaryWriter writer)
        {
            object[] param = null;

            FieldInfo[] fields = this.GetType().GetFields(BindingFlags.Public | BindingFlags.Instance);
           
            foreach(FieldInfo field in fields)
            {
                // Check if we have any value
                object value = field.GetValue(this);
               
                MethodInfo method = (MethodInfo)MarshallingMethods.WriteMethods[field.FieldType];
               
                if (field.FieldType.IsArray)
                {
                    Type element = field.FieldType.GetElementType();
                    if (element.IsValueType && element.IsPrimitive)
                    {
                        //method.Invoke(writer, new object[] {value});
                        Array arrObject = (Array)field.GetValue(this);
                        param = new object[2];
                        param[0] = writer;
                        param[1] = arrObject;
                        method.Invoke(null, param);
                    }
                    else
                    {
                        //Get field size
                        int size = GetFieldSize(field);
                        //Get WriteToStream method
                        method = (MethodInfo)MarshallingMethods.WriteMethods[typeof(CustomMarshaler)];
                        Array arrObject = (Array)field.GetValue(this);
                        for(int i=0;i                        {
                            method.Invoke(arrObject.GetValue(i), new object[]{writer});
                        }
                    }                   
                }
                else if (field.FieldType == typeof(string))
                {   
                    param = new object[3];
                    param[0] = writer;
                    param[1] = field.GetValue(this);
                    param[2] = GetFieldSize(field);
                    method.Invoke(null, param);
                   

                }
                else if (field.FieldType.IsValueType && field.FieldType.IsPrimitive)// regular value type
                {
                    method.Invoke(writer, new object[] {value});
                }
            }
        }

        protected int GetFieldSize(FieldInfo field)
        {
            int size = 0;
            CustomMarshalAsAttribute attrib = (CustomMarshalAsAttribute)field.GetCustomAttributes(typeof(CustomMarshalAsAttribute), true)[0];
           
            if (attrib != null)
            {
                if (attrib.SizeField != null)
                {
                    FieldInfo sizeField = this.GetType().GetField(attrib.SizeField);
                    size = (int)sizeField.GetValue(this);
                }
                else
                {
                    size = attrib.SizeConst;   
                }
            }

            return size;
        }

        #endregion

        helper methods#region helper methods

        private static bool CompareByteArrays (byte[] data1, byte[] data2)
        {
            // If both are null, they're equal
            if (data1==null && data2==null)
            {
                return true;
            }
            // If either but not both are null, they're not equal
            if (data1==null || data2==null)
            {
                return false;
            }
            if (data1.Length != data2.Length)
            {
                return false;
            }
            for (int i=0; i < data1.Length; i++)
            {
                if (data1[i] != data2[i])
                {
                    return false;
                }
            }
            return true;
        }

        #endregion

    }

    MarshallingMethods class#region MarshallingMethods class
    /**////


    /// MarshallingMethods class implementation.
    ///

    public class MarshallingMethods
    {
        public static Hashtable ReadMethods = new Hashtable();
        public static Hashtable WriteMethods = new Hashtable();
       
        constructors#region constructors

        static MarshallingMethods()
        {
            // Read Methods
            ReadMethods.Add(typeof(bool), typeof(BinaryReader).GetMethod("ReadBoolean"));
            ReadMethods.Add(typeof(byte), typeof(BinaryReader).GetMethod("ReadByte"));
            ReadMethods.Add(typeof(System.SByte), typeof(BinaryReader).GetMethod("ReadSByte"));
            ReadMethods.Add(typeof(System.Single), typeof(BinaryReader).GetMethod("ReadSingle"));
            ReadMethods.Add(typeof(byte[]), typeof(BinaryReader).GetMethod("ReadBytes"));
            ReadMethods.Add(typeof(char[]), typeof(BinaryReader).GetMethod("ReadChars"));
            ReadMethods.Add(typeof(System.Int16), typeof(BinaryReader).GetMethod("ReadInt16"));
            ReadMethods.Add(typeof(System.Int32), typeof(BinaryReader).GetMethod("ReadInt32"));
            ReadMethods.Add(typeof(System.UInt16), typeof(BinaryReader).GetMethod("ReadUInt16"));
            ReadMethods.Add(typeof(System.UInt32), typeof(BinaryReader).GetMethod("ReadUInt32"));
            ReadMethods.Add(typeof(System.String), typeof(MarshallingMethods).GetMethod("ReadString"));
            ReadMethods.Add(typeof(System.DateTime), typeof(MarshallingMethods).GetMethod("ReadDateTime"));
            ReadMethods.Add(typeof(System.Int16[]), typeof(MarshallingMethods).GetMethod("ReadInt16Array"));
            ReadMethods.Add(typeof(System.Int32[]), typeof(MarshallingMethods).GetMethod("ReadInt32Array"));
            ReadMethods.Add(typeof(System.UInt16[]), typeof(MarshallingMethods).GetMethod("ReadUInt16Array"));
            ReadMethods.Add(typeof(System.UInt32[]), typeof(MarshallingMethods).GetMethod("ReadUInt32Array"));
            ReadMethods.Add(typeof(CustomMarshaler), typeof(CustomMarshaler).GetMethod("ReadFromStream"));
            //Write Methods
            WriteMethods.Add(typeof(bool), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(bool)}));
            WriteMethods.Add(typeof(byte), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(byte)}));
            WriteMethods.Add(typeof(System.SByte), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(System.SByte)}));
            WriteMethods.Add(typeof(System.Single), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(System.Single)}));
            //WriteMethods.Add(typeof(byte[]), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(byte[])}));
            //WriteMethods.Add(typeof(char[]), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(char[])}));
            WriteMethods.Add(typeof(System.Int16), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(System.Int16)}));
            WriteMethods.Add(typeof(System.Int32), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(System.Int32)}));
            WriteMethods.Add(typeof(System.UInt16), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(System.UInt16)}));
            WriteMethods.Add(typeof(System.UInt32), typeof(BinaryWriter).GetMethod("Write", new Type[]{typeof(System.UInt32)}));
            WriteMethods.Add(typeof(System.String), typeof(MarshallingMethods).GetMethod("WriteString"));
            WriteMethods.Add(typeof(CustomMarshaler), typeof(CustomMarshaler).GetMethod("WriteToStream"));

            WriteMethods.Add(typeof(bool[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(bool[]) }));
            WriteMethods.Add(typeof(char[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(char[]) }));
            WriteMethods.Add(typeof(short[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(short[]) }));
            WriteMethods.Add(typeof(ushort[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(ushort[]) }));
            WriteMethods.Add(typeof(int[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(int[]) }));
            WriteMethods.Add(typeof(uint[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(uint[]) }));
            WriteMethods.Add(typeof(long[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(long[]) }));
            WriteMethods.Add(typeof(ulong[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(ulong[]) }));
            WriteMethods.Add(typeof(float[]), typeof(MarshallingMethods).GetMethod("WriteArray", new Type[] { typeof(BinaryWriter), typeof(float[]) }));

        }

        #endregion

        static helper methods#region static helper methods

        public static short[] ReadInt16Array(BinaryReader reader, int count)
        {
            short[] result = new short[count];

            for(int i=0;i            {
                result[i] = reader.ReadInt16();
            }
            return result;
        }

        public static int[] ReadInt32Array(BinaryReader reader, int count)
        {
            int[] result = new int[count];

            for(int i=0;i            {
                result[i] = reader.ReadInt32();
            }
            return result;
        }

        public static ushort[] ReadUInt16Array(BinaryReader reader, int count)
        {
            ushort[] result = new ushort[count];

            for(int i=0;i            {
                result[i] = reader.ReadUInt16();
            }
            return result;
        }

        public static uint[] ReadUInt32Array(BinaryReader reader, int count)
        {
            uint[] result = new uint[count];

            for(int i=0;i            {
                result[i] = reader.ReadUInt32();
            }
            return result;
        }

        public static string ReadString(BinaryReader reader, int count)
        {
            string result = "";
            if (count == 0)
            {
                count = 255; //default   
            }
            char[] data = reader.ReadChars(count);

            result = new string(data).TrimEnd('\0');
            return result;
        }

        public static void WriteString(BinaryWriter writer, string value, int size)
        {
            if (value!=null)
            {
                byte[] bstring = System.Text.Encoding.Unicode.GetBytes(value.Substring(0, size));
                writer.Write(bstring);
            }
        }

        public static DateTime ReadDateTime(BinaryReader reader)
        {
            return DateTime.FromFileTime(reader.ReadInt64());
        }


        public static void WriteArray(BinaryWriter writer, bool[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, char[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }

        public static void WriteArray(BinaryWriter writer, byte[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }

        public static void WriteArray(BinaryWriter writer, short[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, ushort[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, int[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, uint[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, long[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, ulong[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }
        public static void WriteArray(BinaryWriter writer, float[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                writer.Write(arr[i]);
            }
        }

        public static void WriteSerializers(BinaryWriter writer, CustomMarshaler[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                arr[i].WriteToStream(writer);
            }
        }

        #endregion
    }

    #endregion

    CustomMarshalAsAttribute#region CustomMarshalAsAttribute
    /**////


    /// CustomMarshalAsAttribute implementaion.
    ///

    public sealed class CustomMarshalAsAttribute : Attribute
    {
        public int SizeConst = 0;
        public string  SizeField = null;
    }

    #endregion

}

MIB_IFROW.cs
using System;
using System.Collections.Generic;
using , System.Text;

namespace Lemony.SystemInfo
{
    public class MIB_IFROW : CustomMarshaler
    {
        [CustomMarshalAs(SizeConst = MAX_INTERFACE_NAME_LEN)]
        public string wszName;
        public uint dwIndex; // index of the interface
        public uint dwType; // type of interface
        public uint dwMtu; // max transmission unit
        public uint dwSpeed; // speed of the interface
        public uint dwPhysAddrLen; // length of physical address
        [CustomMarshalAs(SizeConst = MAXLEN_PHYSADDR)]
        public byte[] bPhysAddr; // physical address of adapter
        public uint dwAdminStatus; // administrative status
        public uint dwOperStatus; // operational status
        public uint dwLastChange; // last time operational status changed
        public uint dwInOctets; // octets received
        public uint dwInUcastPkts; // unicast packets received
        public uint dwInNUcastPkts; // non-unicast packets received
        public uint dwInDiscards; // received packets discarded
        public uint dwInErrors; // erroneous packets received
        public uint dwInUnknownProtos; // unknown protocol packets received
        public uint dwOutOctets; // octets sent
        public uint dwOutUcastPkts; // unicast packets sent
        public uint dwOutNUcastPkts; // non-unicast packets sent
        public uint dwOutDiscards; // outgoing packets discarded
        public uint dwOutErrors; // erroneous packets sent
        public uint dwOutQLen; // output queue length
        public uint dwDescrLen; // length of bDescr member
        [CustomMarshalAs(SizeConst = MAXLEN_IFDESCR)]
        public byte[] bDescr; // interface description        

        private const int MAX_INTERFACE_NAME_LEN = 256;
        private const int MAXLEN_PHYSADDR = 8;
        private const int MAXLEN_IFDESCR = 256;
        private const int MAX_ADAPTER_NAME = 128;
    }
}

MIB_IFTABLE.cs
using System;
using System.Collections.Generic;
using System.Text;

namespace Lemony.SystemInfo
{
    /**////


    /// IFTable
    ///

    public class MIB_IFTABLE : CustomMarshaler
    {
        public int dwNumEntries;
        [CustomMarshalAs(SizeField = "dwNumEntries")]
        public MIB_IFROW[] Table;

        public MIB_IFTABLE()
        {
            this.data = new byte[this.GetSize()];
        }

        public MIB_IFTABLE(int size)
        {
            this.data = new byte[size];
        }
    }
}

再定义一个 NetInfo 类,存储网络信息

NetInfo.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;


namespace Lemony.SystemInfo
{
    /**////


    /// 网络类型
    ///

    public enum NetType
    {
        Other = 1,
        Ethernet = 6,
        Tokenring = 9,
        FDDI = 15,
        PPP = 23,
        Loopback = 24,
        Slip = 28
    };

    /**////


    /// 网络状态
    ///

    public enum NetState
    {
        NotOperational = 0,
        Operational = 1,
        Disconnected = 2,
        Connecting = 3,
        Connected = 4,
        Unreachable = 5
    };

    /**////


    /// 网络信息类
    ///

    public class NetInfo
    {
        public NetInfo()
        {
        }

        private string m_Name;
        /**////


        /// 名称
        ///

        public string Name
        {
            get { return m_Name; }
            set { m_Name = value; }
        }

        private uint m_Index;
        /**////


        /// 有效编号
        ///

        public uint Index
        {
            get { return m_Index; }
            set { m_Index = value; }
        }

        private NetType m_Type;
        /**////


        /// 类型
        ///

        public NetType Type
        {
            get { return m_Type; }
            set { m_Type = value; }
        }

        private uint m_Speed;
        /**////


        /// 速度
        ///

        public uint Speed
        {
            get { return m_Speed; }
            set { m_Speed = value; }
        }

        private uint m_InOctets;
        /**////


        /// 总接收字节数
        ///

        public uint InOctets
        {
            get { return m_InOctets; }
            set { m_InOctets = value; }
        }

        private uint m_OutOctets;
        /**////


        /// 总发送字节数
        ///

        public uint OutOctets
        {
            get { return m_OutOctets; }
            set { m_OutOctets = value; }
        }

        private NetState m_Status;
        /**////


        /// 操作状态
        ///

        public NetState Status
        {
            get { return m_Status; }
            set { m_Status = value; }
        }

        private uint m_InErrors;
        /**////


        /// 总错收字节数
        ///

        public uint InErrors
        {
            get { return m_InErrors; }
            set { m_InErrors = value; }
        }

        private uint m_OutErrors;
        /**////


        /// 总错发字节数
        ///

        public uint OutErrors
        {
            get { return m_OutErrors; }
            set { m_OutErrors = value; }
        }

        private uint m_InUnknownProtos;
        /**////


        /// 未知协议共收字节数
        ///

        public uint InUnknownProtos
        {
            get { return m_InUnknownProtos; }
            set { m_InUnknownProtos = value; }
        }

        private string m_PhysAddr;
        /**////


        /// 物理地址
        ///

        public string PhysAddr
        {
            get { return m_PhysAddr; }
            set { m_PhysAddr = value; }
        }

    }
}

OK,现在可以获取网络信息了

        /**////


        /// Get IFTable
        ///

        /// MIB_IFTABLE Class
        private static MIB_IFTABLE GetAllIfTable()
        {
            //缓冲区大小
            uint dwSize = 0;

            //获取缓冲区大小
            uint ret = GetIfTable(null, ref dwSize, false);
            if (ret == 50)
            {
                //此函数仅支持于 win98/nt 系统
                return null;
            }

            //定义,获取 MIB_IFTABLE 对象
            MIB_IFTABLE tbl = new MIB_IFTABLE((int)dwSize);
            ret = GetIfTable(tbl.ByteArray, ref dwSize, false);

            //如果不成功
            if (ret != 0)
            {
                return null;
            }

            return tbl;
        }

        /**////


        /// Get NetInfo Class
        ///

        /// MIB_IFROW Class
        /// NetInfo Class
        private static NetInfo GetNetInfo(MIB_IFROW row)
        {
            NetInfo ninfo = new NetInfo();
            ninfo.Index = row.dwIndex;
            ninfo.Name = Encoding.ASCII.GetString(row.bDescr, 0, (int)row.dwDescrLen);
            ninfo.PhysAddr = GetPhysAddr(row.bPhysAddr, (int)row.dwPhysAddrLen);
            ninfo.Type = (NetType)row.dwType;
            ninfo.Status = (NetState)row.dwOperStatus;
            ninfo.Speed = row.dwSpeed;
            ninfo.InErrors = row.dwInErrors;
            ninfo.InOctets = row.dwInOctets;
            ninfo.InUnknownProtos = row.dwInUnknownProtos;
            ninfo.OutErrors = row.dwOutErrors;
            ninfo.OutOctets = row.dwOutOctets;
            return ninfo;
        }
/**////
        /// 获取所有的网络信息
        ///

        /// NetInfo 网络信息范型
        public static List GetAllNetInfo()
        {
            //定义范型
            List ninfos = new List();

            //定义,获取 MIB_IFTABLE 对象
            MIB_IFTABLE tbl = GetAllIfTable();

            //如果成功
            if (tbl != null)
            {
                tbl.Deserialize();
                for (int i = 0; i < tbl.Table.Length; i++)
                {
                    ninfos.Add(GetNetInfo(tbl.Table[i]));
                }
            }

            return ninfos;
        }
PS:事实上,我把获取网络、CPU、内存、磁盘、进程信息等功能封装起来,并做了一个比较完善的 Windows 任务管理器,整理完后发布源码。

<> <>
关键字词: