MS.Tech - IT人

.NET & 微软企业服务器 & 前沿技术和产品
随笔 - 107, 评论 - 1269, 引用 - 87

导航

关于

所有内容和观点仅代表个人观点,如有问题和建议请发Email给我。

标签

每月存档

最新留言

广告

 

??? 朋友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

留言反馈

#获得局域网中计算机的列表(包括计算机名,IP和MAC)的方法 编辑
有的时候需要根据MAC来限定登录的计算机,为此查找了不少资料(有来自博客堂和CSDN),下面是获得远程计算机的MAC和局域网中计算机列表的方法。
2008-01-29 16:24:00 | [匿名:ChessPlayer]
#回复: 获取本机网卡MAC地址 编辑
function getMAC()
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
2008-01-04 14:00:00 | [匿名:小龙]
#回复: 获取远程网卡MAC地址 编辑
在ASP中如何获取访问机的MAC 码?
2007-11-19 09:28:00 | [匿名:我也在做相关的,]
#获得局域网中计算机的列表(包括计算机名,IP和MAC)的方法 编辑
有的时候需要根据MAC来限定登录的计算机,为此查找了不少资料(有来自博客堂和CSDN),下面是获得远程计算机的MAC和局域网中计算机列表的方法。 需要引用的命名空间 usingSystem;...
2007-10-12 15:45:00 | [匿名:林西]
#回复: 获取远程网卡MAC地址 编辑
我的搞定了 VB C#都OK了
2007-09-02 05:16:00 | [匿名:zw2ky]
#回复: 获取远程网卡MAC地址 编辑
顶呀,我也要弄这个,用C#.net 得到 mac ,哪位大虾帮帮我 zhaoyijuan@126.com,小女子不甚感激
2007-08-24 16:53:00 | [匿名:jelly]
#回复: 获取远程网卡MAC地址 编辑
推荐一个免费的多语种在线翻译网站 http://www.165net.com
2007-08-21 14:44:00 | [匿名:北京翻译公司]
#回复: 获取远程网卡MAC地址 编辑
解决了吗?我也遇到这个问题,现在急需要解决...
2007-08-02 17:59:00 | [匿名:网络]
#回复: 获取远程网卡MAC地址 编辑
解决了吗?
2007-08-02 17:58:00 | [匿名:网络]
#回复: 获取远程网卡MAC地址 编辑
比如我的网卡MAC地址为00-50-BA-29-22-1A,可是转换后的十六进制却是29BA5000。显然是要每两位反过来排序,但是为什么却缺少了 22-1A ?按道理说得到的结果应该是1A2229BA5000。



这个问题解决了吗?
我也遇到改问题了。
2007-07-28 14:52:00 | [匿名:fanzy80@126.com]
#回复: 获取远程网卡MAC地址 编辑
能帮我用C++写一个获取远程机器的MAC地址的程序吗?
我的邮箱是 xdliuyanping@126.com
2007-05-31 11:58:00 | [匿名:星空]
#回复: 获取远程网卡MAC地址 编辑
谢谢 LiMac,我的问题解决了!!!
2007-03-27 15:29:00 | [匿名:了无痕]
#回复: 获取远程网卡MAC地址 编辑
可以给一个完整的工程吗????


my email: zw2ky@163.com

谢谢各位了!!!
2007-03-07 20:34:00 | [匿名:zw2ky]
#获得局域网中计算机的列表(包括计算机名,IP和MAC)的方法 编辑
获得局域网中计算机的列表(包括计算机名,IP和MAC)的方法
2006-09-09 15:34:00 | [匿名:风也红了]
#获得局域网中计算机的列表(包括计算机名,IP和MAC)的方法 编辑
出自:http://zhangweiguo3984.cnblogs.com/articles/313695.html
2006-02-11 14:57:00 | [匿名:花纯春]
#re: 获取远程网卡MAC地址 编辑
你要是做成了,我还有安全感吗?
2006-02-11 13:47:00 | [匿名:www]
#re: 获取远程网卡MAC地址 编辑
我想开发一个ASP组件,实现:1.获取指定IP的MAC地址;2.获取指定MAC地址的IP,不知能否实现?谢谢!
我的email:ejzhang@163.com
2005-11-08 09:18:00 | [匿名:ejzhang]
#re: 获取远程网卡MAC地址 编辑
如何用VB6.0实现呢??VB6.0中没有64位整数啊,怎么在VB中使用使用64位整数的SendARP呢??
2005-10-12 09:43:00 | [匿名:w]
#re: 获取远程网卡MAC地址 编辑
Dos 命令 ipconfig/all
2005-10-11 10:55:00 | [匿名:malen]
#re: 获取远程网卡MAC地址 编辑
怎么用DOS命令获得?
2005-08-16 12:58:00 | [匿名:duhuaqiao]
#如何通过局域网中的机器名获得MAC 编辑
请回复foryouyhlp@126.com
2005-07-18 17:41:00 | [匿名:han]
#re: 获取远程网卡MAC地址 编辑
他妈的! 假地! 就得了个0
2005-05-18 07:53:00 | [匿名:靠靠]
#re: 获取远程网卡MAC地址 编辑
使用WMI获取远程MAC的例子有吗?
我只有一个获得本地机器的方法。
2005-05-08 16:34:00 | [匿名:Jason]
#re: 获取远程网卡MAC地址 编辑
<font size=24 color=red>用asp 获取远程网卡MAC地址</font>
2005-04-30 15:57:00 | [匿名:sss]
#re: 获取远程网卡MAC地址 编辑
跨路由无法适用ARP,需要使用WINS查询了
2005-04-07 12:52:00 | [匿名:Hao Hu]
#re: 获取远程网卡MAC地址 编辑
如何跨路由获取呀,快找遍因特网了,也没有解决!!!
2005-03-22 17:53:00 | [匿名:tqg1023]
#re: 获取远程网卡MAC地址 编辑
朋友是跨网段获取MAC地址哦, 并不是同一NAT下的一址
2005-01-19 13:52:00 | [匿名:aaa]
#re: 获取远程网卡MAC地址 编辑
怎么用c来实现啊???
麻烦楼主帮忙了!
2004-12-23 12:41:00 | [匿名:zyan]
#re: 获取远程网卡MAC地址 编辑
访问遭到拒绝
ManagementObjectSearcher searcher = new
ManagementObjectSearcher("SELECT * FROM Win32_NetworkAdapterConfiguration");
foreach (ManagementObject share in searcher.Get())
{
TextBox1.Text+=share["MACAddress"].ToString();
}
2004-12-09 22:00:00 | [匿名:test]
#re: 获取远程网卡MAC地址 编辑
using System;
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);
}

}
}
2004-11-16 23:19:00 | [匿名:LiMac]
#re: 获取远程网卡MAC地址 编辑
为什么有个别IP地址的MAC提起不到,此IP在线
2004-11-15 14:58:00 | [匿名:wb]
#re: 获取远程网卡MAC地址 编辑
请教:VB如何编程获取远程(同一局域网内)网卡信息?
2004-11-08 12:16:00 | [匿名:ZZZ]
#re: 获取远程网卡MAC地址 编辑
我还没有上网,不知那是什么?怎么找
2004-09-07 20:14:00 | [匿名:忍心]
#re: 获取远程网卡MAC地址 编辑
我想请问一下,IntPtr类型的MAC地址转换为十六进制,怎么转换
从程序中获取自己的MAC号是整串数字1078779904,而MAC地址却是
E04c4031c0,根本就没有办法转过来
2004-08-24 10:42:00 | [匿名:黄玮璘]
#回复: 获取远程网卡MAC地址 编辑
to janson: add the following code:

using System.Runtime.InteropServices;
2004-06-26 15:41:00 | [匿名:纯朴的狗熊]
#回复: 获取远程网卡MAC地址 编辑
为什么我录入以上代码编译时提示:The type or namespace name 'DllImport' could not be found (are you missing a using directive or an assembly reference?)

2004-06-26 11:32:00 | [匿名:Janson]
#回复: 获取本机网卡的MAC地址和IRQ 编辑
快来帮帮我吧!
如何获取本机网卡的参数,如MAC地址。
2004-05-20 10:40:00 | [匿名:潇潇]
#回复: 获取远程网卡MAC地址 编辑
qqqswswqsq
2004-05-17 16:00:00 | [匿名:qqq]
#回复: 获取远程网卡MAC地址 编辑
如何在asp页面中读取远程网卡mac地址
2004-05-06 19:00:00 | [匿名:欧阳]
#回复: 获取远程网卡MAC地址 编辑
救急!!!如何在asp中用vb script得到MAC呢?
2004-04-25 12:23:00 | [匿名:amywei]
#回复: 获取远程网卡MAC地址 编辑
为什么我在获取本地MAC的时候 回有访问拒绝的信息 呢
2004-04-07 08:56:00 | [匿名:wsb]
#回复: 获取远程网卡MAC地址 编辑
似的.应在程序集中引用
2004-03-14 13:13:00 | [匿名:钝出]
#回复: 获取远程网卡MAC地址 编辑
“添加引用”-->“.NET组件”-->找到System.Management.dll组件。按引用即可拉。
2004-02-23 15:47:00 | [匿名:纯朴的狗熊]
#using System.Management;出错! 编辑
提示: 类型或命名空间名称“Management”在类或命名空间“System”中不存在(是否缺少程序集引用?)——怎么回事?
2004-02-23 09:42:00 | [匿名:山水]
#回复: 获取远程网卡MAC地址 编辑
引用下 System.Management 这个.net组件就行了.
2004-02-22 15:43:00 | [匿名:纯朴的狗熊]
#我的.Net Studio怎么没有System.Management命名空间呢? 编辑
如何获得System.Management?
2004-02-20 16:13:00 | [匿名:山水]
#回复: 获取远程网卡MAC地址 编辑
不应该用IntPtr的。通过它只能访问到Int32(在32位平台上)大小的内容。
下面修改过的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地址的。
2003-12-23 22:55:00 | [匿名:backend]
对不起,目前本随笔不允许发表新评论.

Powered by: Joycode.MVC引擎 0.5.2.0