??? 朋友mingal急问我有关获取远程网卡MAC地址的ASP.net实现。我一开始以为是获取本机MAC地址,说了几种方法给他。由于他还需要获取服务器(本机)相关信息,如硬盘序列号、CPU信息等。于是介绍了个WMI方法给他:
using System.Management;
string strMac = string.Empty;
ManagementClass mc = new ManagementClass("Win32_NetworkAdapterConfiguration");
ManagementObjectCollection moc = mc.GetInstances();
???
foreach(ManagementObject mo in moc)
{
???? if ((bool)mo["IPEnabled"] == true)
?? ? {
???? ?strMac += mo["MacAddress"].ToString() + "
";
???? }
}
??? 后来才知道他要的是局域网浏览用户的网卡的MAC地址,那可犯难了。后来找到了相关实现代码,大致是使用地址转换协议进行广播查询的,主要是SendArp这个API:
DWORD SendARP(
? IPAddr DestIP,???? // 目的IP 地址
? IPAddr SrcIP,????? // 源IP地址,可选参数,把它填成0不会有问题
? PULONG pMacAddr,?? // 返回的物理地址
? PULONG PhyAddrLen? // 物理地址的长度
);
在C#中实现为:
[DllImport("Iphlpapi.dll")]
private static extern int SendARP(Int32 dest,Int32 host,ref IntPtr mac,ref IntPtr length);
[DllImport("Ws2_32.dll")]
private static extern Int32 inet_addr(string ip);
private IntPtr getRemoteMAC(string localIP, string remoteIP)
{
?? ??Int32 ldest= inet_addr(remoteIP);? //目的地的ip
??? ?Int32 lhost= inet_addr(localIP);???? ?//本地服务器的ip
???try
???{
???? ?Byte[] macinfo=new Byte[6];
??? ??IntPtr mac=new IntPtr(macinfo[0]);
???? ?IntPtr len=new IntPtr
;
??????int ii=SendARP(ldest,lhost, ref mac, ref len);
???? ?return mac;
???}
???catch(Exception err)
???{
???}
???? ?return IntPtr.Zero;
}
??? 可是当把得到的IntPtr类型的MAC地址转换为十六进制时,出现了令人不解的一幕。比如我的网卡MAC地址为00-50-BA-29-22-1A,可是转换后的十六进制却是29BA5000。显然是要每两位反过来排序,但是为什么却缺少了 22-1A ?按道理说得到的结果应该是1A2229BA5000。另外,Arp只能获得同一个网段的,不能跨网段!郁闷ing……,有什么更好的方法???
打印 | 张贴于 2003-12-23 15:01:00 | Tag:ASP.NET
留言反馈
dim a,b,mac,wsh,fso,text
mac=""
set wsh=server.CreateObject("Wscript.shell")
wsh.run "%comspec% /c ipconfig /all >c:\aaa.txt",0,true
set wsh=nothing
set fso=server.CreateObject("scripting.filesystemobject")
set text=fso.opentextfile("c:\aaa.txt")
a=split(text.readall,":")
text.close
fso.deletefile "c:\aaa.txt"
set fso=nothing
if isarray(a) then
for i=0 to ubound(a)
b=split(a(i),"-")
if isarray(b) then
if ubound(b)>2 then
b(ubound(b))=left(b(ubound(b)),2)
for j=0 to ubound(b)
if j=0 then
mac=b(j)
else
mac=mac&"-"&b(j)
end if
next
exit for
end if
end if
next
end if
getmac=mac
end function
这个问题解决了吗?
我也遇到改问题了。
我的邮箱是 xdliuyanping@126.com
my email: zw2ky@163.com
谢谢各位了!!!
我的email:ejzhang@163.com
我只有一个获得本地机器的方法。
麻烦楼主帮忙了!
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration");
foreach (ManagementObject share in searcher.Get())
{
TextBox1.Text+=share["MACAddress"].ToString();
}
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Runtime.InteropServices;
namespace SUEM.AppModule.Net
{
/// <summary>
/// IP 的摘要说明。
/// </summary>
public class IP
{
[DllImport("Iphlpapi.dll")]
private static extern int SendARP(Int32 dest,Int32 host,ref Int64 mac,ref Int32 length);
[DllImport("Ws2_32.dll")]
private static extern Int32 inet_addr(string ip);
private string ipAddress,myIpAddress,macAddress,hostName;
private bool canPing=false;
#region 用于测试PING的局部变量
private Socket socket;
int nBytes=-1,timeConsume=0;
bool PingSucess=false;
Byte[] ReceiveData=new Byte[256]; // 接收数据缓冲
private IPAddress hostIPAddress;
private IPAddress clientIPAddress;
private EndPoint hostPoint; // 服务器的网络地址
private EndPoint clientPoint; // 客户端的网络地址
private int startTime;
private Thread ReceivePing;
static TimeSpan waitTime=new TimeSpan(0,0,0,3);
#endregion
public IP()
{
ipAddress="127.0.0.1";
myIpAddress="127.0.0.1";
GetMacAddress();
}
public IP(string IPAddress)
{
ipAddress=IPAddress;
myIpAddress="127.0.0.1";
GetMacAddress();
hostIPAddress=System.Net.IPAddress.Parse(ipAddress);
clientIPAddress=System.Net.IPAddress.Parse(myIpAddress);
hostPoint=(EndPoint)new IPEndPoint(hostIPAddress ,0); // 服务器的网络地址
clientPoint=(EndPoint)new IPEndPoint(clientIPAddress,0); // 客户端的网络地址
}
public IP(IPAddress IPAddress)
{
ipAddress=IPAddress.Address.ToString();
myIpAddress="127.0.0.1";
GetMacAddress();
}
public IP(IPHostEntry IPAddress)
{
ipAddress=IPAddress.AddressList[0].ToString();
myIpAddress="127.0.0.1";
GetMacAddress();
}
public void GetMacAddress() // 得到指定IP的MAC地址
{
Int32 ldest=inet_addr(ipAddress);
Int64 macinfo=new Int64();
Int32 len=6;
try
{
int res=SendARP(ldest,0,ref macinfo,ref len);
}
catch(Exception err)
{
throw new Exception("在解析MAC地址过程发生了错误!");
}
string originalMACAddress=macinfo.ToString("X4");
if(originalMACAddress!="0000" && originalMACAddress.Length==12)
{ //合法MAC地址
string mac1,mac2,mac3,mac4,mac5,mac6;
mac1=originalMACAddress.Substring(10,2);
mac2=originalMACAddress.Substring(8,2);
mac3=originalMACAddress.Substring(6,2);
mac4=originalMACAddress.Substring(4,2);
mac5=originalMACAddress.Substring(2,2);
mac6=originalMACAddress.Substring(0,2);
macAddress=mac1+"-"+mac2+"-"+mac3+"-"+mac4+"-"+mac5+"-"+mac6;
canPing=true;
}
else
{
macAddress="00-00-00-00-00-00";
canPing=false;
}
}
public bool PingPass(int PingTime,int PingDelay,out int SendReceiveTime)
{
socket=new Socket(AddressFamily.InterNetwork,SocketType.Raw,ProtocolType.Icmp); // 创建一个ICMP的Socket连接
// 设置ICMP报文
int DataSize=32; //ICMP数据包大小
int PacketSize=DataSize+8; // 总报文长度
const int ICMP_ECHO=8;
IcmpPacket packet=new IcmpPacket(ICMP_ECHO,0,0,45,0,DataSize);
//将ICMP报文信息和数据转换为byte数据包
Byte[] buffer=new Byte[PacketSize];
int index=packet.ConvertToByte(buffer);
//校验和的计算
int count=(int)Math.Ceiling(((Double)index)/2);
UInt16[] Buffer2=new UInt16[count];
index=0;
for(int i=0;i<count;i++)
{
//将2个byte转换为一个UInt16
Buffer2[i]=BitConverter.ToUInt16(buffer,index);
index+=2;
}
// 将校验和保存至报文里
packet.CheckSum=IcmpPacket.SumOfCheck(Buffer2);
// 保存校验和后,再次将报文转化为数据包
Byte[] SendData=new Byte[PacketSize];
index=packet.ConvertToByte(SendData);
for(int i=0;i<PingTime;i++)
{
int nBytes=0;
startTime=Environment.TickCount;
nBytes=socket.SendTo(SendData,PacketSize,SocketFlags.None,(EndPoint)hostPoint); // 发送数据包
ReceivePing=new Thread(new ThreadStart(ReceiveICMPData));
while(timeConsume<PingDelay || PingSucess!=true || ReceivePing.ThreadState==ThreadState.Aborted) // 反复接收ICMP数据包
{
#region 利用线程
ReceivePing.Start();
if(ReceivePing.Join(waitTime))
{
break;
}
#endregion
#region 不利用线程
/*
timeConsume=System.Environment.TickCount-startTime;
nBytes=socket.ReceiveFrom(ReceiveData,256,SocketFlags.None,ref clientPoint); // 接收数据
if(nBytes!=-1)
{
PingSucess=true;
}
*/
#endregion
//ReceiveThread.Start();
} // end while 结束一次接收
if(PingSucess) break;
} // end for 结束几次ping的过程
socket.Close();
SendReceiveTime=timeConsume;
this.canPing=PingSucess;
return PingSucess;
}
public void ReceiveICMPData()
{
timeConsume=System.Environment.TickCount-startTime;
nBytes=socket.ReceiveFrom(ReceiveData,256,SocketFlags.None,ref clientPoint); // 接收数据
if(nBytes!=-1)
{
PingSucess=true;
}
}
public string GetHostName() // 得到指定IP的机器名
{
try
{
IPHostEntry remoteHost=Dns.GetHostByAddress(ipAddress);
hostName=remoteHost.HostName;
}
catch(Exception err1)
{
hostName="无法得到机器名";
}
return hostName;
}
public string IpAddress
{
get
{
return ipAddress;
}
}
public string MyIpAddress
{
get
{
return myIpAddress;
}
}
public string MacAddress
{
get
{
return macAddress;
}
}
public string HostName
{
get
{
return hostName;
}
}
public bool CanPing
{
get
{
return canPing;
}
}
}
/// <summary>
/// 初始话ICMP报文
/// </summary>
public class IcmpPacket
{
private Byte _type; //报文类型
private Byte _subCode; //字代码类型
private UInt16 _checkSum; //报文校验和
private UInt16 _identifier; //识别符
private UInt16 _sequenceNumber; //序列号
private Byte[] _data; //数据包
public IcmpPacket(Byte type,Byte subCode,UInt16 checkSum,UInt16 identifier,UInt16 sequenceNumber,int dataSize)
{
_type=type;
_subCode=subCode;
_checkSum=checkSum;
_identifier=identifier;
_sequenceNumber=sequenceNumber;
_data=new Byte[dataSize];
for(int i=0;i<dataSize;i++)
{
_data[i]=(byte)'#'; // 组织一个以"#"为内容的空ICMP报文
}
}
public UInt16 CheckSum
{
get
{
return _checkSum;
}
set
{
_checkSum=value;
}
}
// 将整个ICMP报文信息和数据转化为Byte数据包(组包到buffer中,并返回总长度i)
public int ConvertToByte(Byte[] buffer)
{
Byte[] b_type=new Byte[1]{_type};
Byte[] b_code=new Byte[1]{_subCode};
Byte[] b_cksum=BitConverter.GetBytes(_checkSum);
Byte[] b_id=BitConverter.GetBytes(_identifier);
Byte[] b_seq=BitConverter.GetBytes(_sequenceNumber);
int i=0;
Array.Copy(b_type,0,buffer,i,b_type.Length);
i+=b_type.Length;
Array.Copy(b_code,0,buffer,i,b_code.Length);
i+=b_code.Length;
Array.Copy(b_cksum,0,buffer,i,b_cksum.Length);
i+=b_cksum.Length;
Array.Copy(b_id,0,buffer,i,b_id.Length);
i+=b_id.Length;
Array.Copy(b_seq,0,buffer,i,b_seq.Length);
i+=b_seq.Length;
Array.Copy(_data,0,buffer,i,_data.Length);
i+=_data.Length;
return i;
}
// 根据ICMP报文协议进行校验和计算
public static UInt16 SumOfCheck(UInt16[] buffer)
{
int sum=0;
for(int i=0;i<buffer.Length;i++)
{
sum+=(int)buffer[i];
sum=(sum>>16)+(sum & 0xffff);
sum+=(sum>>16);
}
return (UInt16)(~sum);
}
}
}
从程序中获取自己的MAC号是整串数字1078779904,而MAC地址却是
E04c4031c0,根本就没有办法转过来
using System.Runtime.InteropServices;
如何获取本机网卡的参数,如MAC地址。
下面修改过的C#代码已验证通过(未将网络字节顺序转换为主机字节顺序):
[DllImport("Iphlpapi.dll")]
private static extern int SendARP(Int32 dest,Int32 host,ref Int64 mac,ref Int32 length);
[DllImport("Ws2_32.dll")]
private static extern Int32 inet_addr(string ip);
static private Int64 getRemoteMAC(string localIP, string remoteIP)
{
Int32 ldest= inet_addr(remoteIP); //目的地的ip
Int32 lhost= inet_addr(localIP); //本地服务器的ip
try
{
Int64 macinfo = new Int64();
Int32 len = 6;
int res = SendARP(ldest,0, ref macinfo, ref len);
return macinfo;
}
catch(Exception err)
{
Console.WriteLine("Error:{0}",err.Message);
}
return 0;
}
至于第二个问题,在标准网络协议下,ARP包是不可能跨网段传输的,故想通
过ARP协议是无法查询跨网段设备MAC地址的。