首页 > 开发 > 综合 > 正文

在C#中调用API获取网络信息和流量

2024-07-21 02:26:06
字体:
来源:转载
供稿:网友

最近一项目中要求显示网络流量,而且必须使用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
{
   
    /**//// <summary>
    /// custommarshaler class implementation.
    /// </summary>
    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<size;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<size;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
    /**//// <summary>
    /// marshallingmethods class implementation.
    /// </summary>
    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<count;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<count;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<count;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<count;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
    /**//// <summary>
    /// custommarshalasattribute implementaion.
    /// </summary>
    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
{
    /**//// <summary>
    /// iftable
    /// </summary>
    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
{
    /**//// <summary>
    /// 网络类型
    /// </summary>
    public enum nettype
    {
        other = 1,
        ethernet = 6,
        tokenring = 9,
        fddi = 15,
        ppp = 23,
        loopback = 24,
        slip = 28
    };

    /**//// <summary>
    /// 网络状态
    /// </summary>
    public enum netstate
    {
        notoperational = 0,
        operational = 1,
        disconnected = 2,
        connecting = 3,
        connected = 4,
        unreachable = 5
    };

    /**//// <summary>
    /// 网络信息类
    /// </summary>
    public class netinfo
    {
        public netinfo()
        {
        }

        private string m_name;
        /**//// <summary>
        /// 名称
        /// </summary>
        public string name
        {
            get { return m_name; }
            set { m_name = value; }
        }

        private uint m_index;
        /**//// <summary>
        /// 有效编号
        /// </summary>
        public uint index
        {
            get { return m_index; }
            set { m_index = value; }
        }

        private nettype m_type;
        /**//// <summary>
        /// 类型
        /// </summary>
        public nettype type
        {
            get { return m_type; }
            set { m_type = value; }
        }

        private uint m_speed;
        /**//// <summary>
        /// 速度
        /// </summary>
        public uint speed
        {
            get { return m_speed; }
            set { m_speed = value; }
        }

        private uint m_inoctets;
        /**//// <summary>
        /// 总接收字节数
        /// </summary>
        public uint inoctets
        {
            get { return m_inoctets; }
            set { m_inoctets = value; }
        }

        private uint m_outoctets;
        /**//// <summary>
        /// 总发送字节数
        /// </summary>
        public uint outoctets
        {
            get { return m_outoctets; }
            set { m_outoctets = value; }
        }

        private netstate m_status;
        /**//// <summary>
        /// 操作状态
        /// </summary>
        public netstate status
        {
            get { return m_status; }
            set { m_status = value; }
        }

        private uint m_inerrors;
        /**//// <summary>
        /// 总错收字节数
        /// </summary>
        public uint inerrors
        {
            get { return m_inerrors; }
            set { m_inerrors = value; }
        }

        private uint m_outerrors;
        /**//// <summary>
        /// 总错发字节数
        /// </summary>
        public uint outerrors
        {
            get { return m_outerrors; }
            set { m_outerrors = value; }
        }

        private uint m_inunknownprotos;
        /**//// <summary>
        /// 未知协议共收字节数
        /// </summary>
        public uint inunknownprotos
        {
            get { return m_inunknownprotos; }
            set { m_inunknownprotos = value; }
        }

        private string m_physaddr;
        /**//// <summary>
        /// 物理地址
        /// </summary>
        public string physaddr
        {
            get { return m_physaddr; }
            set { m_physaddr = value; }
        }

    }
}

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

        /**//// <summary>
        /// get iftable
        /// </summary>
        /// <returns>mib_iftable class</returns>
        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;
        }

        /**//// <summary>
        /// get netinfo class
        /// </summary>
        /// <param name="row">mib_ifrow class</param>
        /// <returns>netinfo class</returns>
        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;
        }
/**//// <summary>
        /// 获取所有的网络信息
        /// </summary>
        /// <returns>netinfo 网络信息范型</returns>
        public static list<netinfo> getallnetinfo()
        {
            //定义范型
            list<netinfo> ninfos = new list<netinfo>();

            //定义,获取 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 任务管理器,整理完后发布源码。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表