您的位置:首页 > 理论基础 > 计算机网络

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

2008-08-25 12:26 501 查看
最近一项目中要求显示网络流量,而且必须使用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 任务管理器,整理完后发布源码。

posted on 2007-03-29 16:43 柠檬的 阅读(1534) 评论(5) 编辑 收藏 所属分类: 技术
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  网络 c# api null byte stream