如何获取本机MAC地址 和 IP

http://hi.baidu.com/baibaiwei/blog/item/2712a8012e1348021d9583cf.html

 

摘要 :本文提供了在Windows操作系统下,获取本机MAC地址的三种方法。
我们在编写网络相关的程序时,经常会遇到需要获取本机MAC地址的问题。如何获取本机的MAC地址?在Windows操作系统下,用户可能马上会想到用ipconfig/all命令,但如果需要在程序中获得怎么办?本文给出了几种简单、常用的方法。
1. 利用 UUID 获取
在Windows操作系统下,以Client-Sever模式进行通信时,运行时间库为了区分每个接口,需要为个接口建立一个 UUID(Universally Unique Identifiers),在Windows95/98版本下,UUID的创建是通过调用函数UuidCreate()完成的,其中的第2至8字节包含了 用户的MAC地址。因此,一种比较快的获取MAC地址的方法是创建一个UUID,然后分析UUID结构的第2至8字节,既可获取本机的MAC地址。示例程 序如下:
static void GetMACaddress(void)
{
unsigned char MACData[6];
UUID uuid;
UuidCreate( &uuid );    // 要求操作系统创建一个新的UUID
for (int i=2; i<8; i++) // 获取本机MAC地址
    MACData[i - 2] = uuid.Data4[i];
PrintMACaddress(MACData);  
}
void PrintMACaddress(unsigned char MACData[])
{
     printf("MAC Address: %02X-%02X-%02X-%02X-%02X-%02X/n",
                 MACData[0], MACData[1], MACData[2], MACData[3], MACData[4], MACData[5]);
}
这种方法只能用于Windows95/98操作系统。因为从安全的角度来看,在网络上散布本机的MAC地址存在着安 全隐患,因此在Windows2000/xp操作系统中,微软对函数UuidCreate()进行了修正,使之在生成UUID时,不借助于本机的MAC地 址。原来UuidCreate()完成的功能由函数UuidCreateSequential()完成。因此,如果在新的系统中采用这种方法,可用 UuidCreateSequential()代替上述程序中的UuidCreate()函数。
     另外,需要说明的是,这种方式只能用于单网卡主机。
2. 利用 Net Bios 协议获取
这种方法在Windows 95/98/Me/NT/2000/XP下都适用,不过它要求网卡必须安装正确,绑定了NetBios协议,并且机器正联接在一个运行正常的 NetBios网络上。如果主机未接在网上,即使用网卡运行正常,运行下述代码,用户也不会得到任何信息。
static void GetMACaddress(void)
{
unsigned char MAC Data[8];      // 定义存放 MAC地址的缓冲区 (至少6字节)
WKSTA_TRANSPORT_INFO_0 *pwkti;
DWORD dwEntriesRead;
DWORD dwTotalEntries;
BYTE *pbBuffer;
   
// 通过 NetBIOS的枚举函数获取MAC地址
NET_API_STATUS dwStatus = NetWkstaTransportEnum(
   NULL,                 // [input] 服务器名,0指本机
   0,                    // [input] 0指函数返回指向WKSTA_TRANSPORT_INFO_0结构的指针
   &pbBuffer,            // [output] 指向缓冲区指针
   MAX_PREFERRED_LENGTH, // [input] 缓冲区最大长度
   &dwEntriesRead,       // [output] 用于记录实际元素个数
   &dwTotalEntries,       //
   NULL);                //[input/output] 恢复句柄
assert(dwStatus == NERR_Success);
pwkti = (WKSTA_TRANSPORT_INFO_0 *)pbBuffer; // 指针类型转换
for(DWORD i=0; i< dwEntriesRead; i++)
{                                          // 读取并打印MAC地址
    swscanf((wchar_t *)pwkti[i].wkti0_transport_address,
            L"%2hx%2hx%2hx%2hx%2hx%2hx",
            &MACData[0],
            &MACData[1],
            &MACData[2],
            &MACData[3],
            &MACData[4],
            &MACData[5]);
    PrintMACaddress(MACData);
}
// 释放缓冲区
dwStatus = NetApiBufferFree(pbBuffer);
assert(dwStatus == NERR_Success);
}
3. 利用 GetAdaptersInfo ()函数获取
此方法利用了Windows SDK 中的函数GetAdaptersInfo(),对于用户来讲,编程很简单,而且适用于Windows 95/98/Me/NT/XP等操作系统,并且不要求主机必须接在网络上,要求的只有一点,就是网卡在Windows下必须是可用的。同时,需要说明的 是,GetAdaptersInfo()是一个功能非常强大的函数,它不但可以得到本机的MAC地址,而且可以得到许多其它相关信息。详细内容可参见 MSDN中有关IP_ADAPTER_INFO结构的说明。
static void GetMACaddress(void)
{
IP_ADAPTER_INFO AdapterInfo[16];       // 定义网卡信息存贮区。
   DWORD dwBufLen = sizeof(AdapterInfo);
   DWORD dwStatus = GetAdaptersInfo(     
    AdapterInfo,                 // [output] 指向接收数据缓冲指针
    &dwBufLen);                  // [input] 缓冲区大小
   assert(dwStatus == ERROR_SUCCESS); // 此处是个trap,用来保证返回值有效
   PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
do {
         PrintMACaddress(pAdapterInfo->Address); // 打印MAC地址
          pAdapterInfo = pAdapterInfo->Next;   
}
while(pAdapterInfo);  
}
本程序中定义了一个长度为16的IP_ADAPTER_INFO结构类型的数组,因此用户主机安装的网卡数不能超过16块,这在一般情况下都是可以满足的,如果出现超过16块的情况,用户需修改此项设置,或采用动态申请存贮空间的方式解决。
4 .结束语

以上三种方法均在Visual C++ 6.0、Windows2000 环境下编译通过并工作正常。需要说明的是,示例程序只是提供了一种解决问题的思路,从软件工程的角度来看,有些不尽人意的地方,读者可以根据自己的编程需要进行修改。

5,获取IP

void CheckIP(void)
{
WSADATA wsaData;
char name[155];
char *ip;
PHOSTENT hostinfo;
if ( WSAStartup( MAKEWORD(2,0), &wsaData ) == 0 ) {
if( gethostname ( name, sizeof(name)) == 0) {
if((hostinfo = gethostbyname(name)) != NULL) { //这些就是获得IP的函数
ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);

printf("%s/n",ip);
}
}
WSACleanup( );
} }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值