如何以跨平台的方式获取

如何以跨平台的方式获取

本文介绍了如何以跨平台的方式获取(几乎)唯一的系统标识符?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种获取数字的方法,该数字在不同计算机上运行代码时几乎肯定会更改,并且几乎肯定在同一计算机上两次运行之间保持不变。

I'm looking for a way to get a number which will almost surely change when running the code on different machines and almost surely stay the same between two runs on the same machine.

如果我是在Linux中将其作为shell脚本执行的,我会使用类似这样的东西:

If I were doing this as a shell script in Linux, I would use something like this:

{ uname -n ; cat /proc/meminfo | head -n1 ; cat /proc/cpuinfo ; } | md5sum

但是我需要C ++(带有boost),至少在Windows,Linux和Mac上需要。

But I need this in C++ (with boost) and at least on Windows, Linux and Mac.

推荐答案

要生成大多数唯一的机器ID,您可以从系统上的各种硬件中获得一些序列号。大多数处理器都有一个CPU序列号,每个硬盘都有一个数字,每个网卡都有一个唯一的MAC地址。

To generate a mostly unique machine id, you can get a few serial numbers from various pieces of hardware on the system. Most processors will have a CPU serial number, the hard disks each have a number, and each network card will have a unique MAC address.

您可以获取并构建一个机器的指纹。您可能需要在声明新机器之前允许更改其中一些数字。 (例如,如果三分之二相同,则机器也相同)。因此,您可以通过升级组件来进行一些优雅的处理。

You can get these and build a fingerprint for the machine. You might want to allow some of these numbers to change before declaring it a new machine. ( e.g. if the 2 out of three are the same, then the machine is the same ). So you can deal somewhat gracefully from having a component upgraded.

我已经从我的一个项目中裁剪了一些代码来获取这些数字。

I've clipped some code from one of my projects that gets these numbers.

Windows:

#include "machine_id.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <intrin.h>
#include <iphlpapi.h>
#ifndef _MSC_VER
#include <cpuid.h>
#else
#include <intrin.h>
#endif

// we just need this for purposes of unique machine id. So any one or two mac's is
// fine.
u16 hashMacAddress( PIP_ADAPTER_INFO info )
{
   u16 hash = 0;
   for ( u32 i = 0; i < info->AddressLength; i++ )
   {
      hash += ( info->Address[i] << (( i & 1 ) * 8 ));
   }
   return hash;
}

void getMacHash( u16& mac1, u16& mac2 )
{
   IP_ADAPTER_INFO AdapterInfo[32];
   DWORD dwBufLen = sizeof( AdapterInfo );

   DWORD dwStatus = GetAdaptersInfo( AdapterInfo, &dwBufLen );
   if ( dwStatus != ERROR_SUCCESS )
      return; // no adapters.

   PIP_ADAPTER_INFO pAdapterInfo = AdapterInfo;
   mac1 = hashMacAddress( pAdapterInfo );
   if ( pAdapterInfo->Next )
      mac2 = hashMacAddress( pAdapterInfo->Next );

   // sort the mac addresses. We don't want to invalidate
   // both macs if they just change order.
   if ( mac1 > mac2 )
   {
      u16 tmp = mac2;
      mac2 = mac1;
      mac1 = tmp;
   }
}

u16 getVolumeHash()
{
   DWORD serialNum = 0;

   // Determine if this volume uses an NTFS file system.
   GetVolumeInformation( "c:\\", NULL, 0, &serialNum, NULL, NULL, NULL, 0 );
   u16 hash = (u16)(( serialNum + ( serialNum >> 16 )) & 0xFFFF );

   return hash;
}

u16 getCpuHash()
{
   int cpuinfo[4] = { 0, 0, 0, 0 };
   __cpuid( cpuinfo, 0 );
   u16 hash = 0;
   u16* ptr = (u16*)(&cpuinfo[0]);
   for ( u32 i = 0; i < 8; i++ )
      hash += ptr[i];

   return hash;
}

const char* getMachineName()
{
   static char computerName[1024];
   DWORD size = 1024;
   GetComputerName( computerName, &size );
   return &(computerName[0]);
}

Linux和OsX:

Linux and OsX:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <assert.h>

#ifdef DARWIN
#include <net/if_dl.h>
#include <ifaddrs.h>
#include <net/if_types.h>
#else //!DARWIN
// #include <linux/if.h>
// #include <linux/sockios.h>
#endif //!DARWIN

const char* getMachineName()
{
   static struct utsname u;

   if ( uname( &u ) < 0 )
   {
      assert(0);
      return "unknown";
   }

   return u.nodename;
}


//---------------------------------get MAC addresses ------------------------------------unsigned short-unsigned short----------
// we just need this for purposes of unique machine id. So any one or two mac's is fine.
unsigned short hashMacAddress( unsigned char* mac )
{
   unsigned short hash = 0;

   for ( unsigned int i = 0; i < 6; i++ )
   {
      hash += ( mac[i] << (( i & 1 ) * 8 ));
   }
   return hash;
}

void getMacHash( unsigned short& mac1, unsigned short& mac2 )
{
   mac1 = 0;
   mac2 = 0;

#ifdef DARWIN

   struct ifaddrs* ifaphead;
   if ( getifaddrs( &ifaphead ) != 0 )
      return;

   // iterate over the net interfaces
   bool foundMac1 = false;
   struct ifaddrs* ifap;
   for ( ifap = ifaphead; ifap; ifap = ifap->ifa_next )
   {
      struct sockaddr_dl* sdl = (struct sockaddr_dl*)ifap->ifa_addr;
      if ( sdl && ( sdl->sdl_family == AF_LINK ) && ( sdl->sdl_type == IFT_ETHER ))
      {
          if ( !foundMac1 )
          {
             foundMac1 = true;
             mac1 = hashMacAddress( (unsigned char*)(LLADDR(sdl))); //sdl->sdl_data) + sdl->sdl_nlen) );
          } else {
             mac2 = hashMacAddress( (unsigned char*)(LLADDR(sdl))); //sdl->sdl_data) + sdl->sdl_nlen) );
             break;
          }
      }
   }

   freeifaddrs( ifaphead );

#else // !DARWIN

   int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP );
   if ( sock < 0 ) return;

   // enumerate all IP addresses of the system
   struct ifconf conf;
   char ifconfbuf[ 128 * sizeof(struct ifreq)  ];
   memset( ifconfbuf, 0, sizeof( ifconfbuf ));
   conf.ifc_buf = ifconfbuf;
   conf.ifc_len = sizeof( ifconfbuf );
   if ( ioctl( sock, SIOCGIFCONF, &conf ))
   {
      assert(0);
      return;
   }

   // get MAC address
   bool foundMac1 = false;
   struct ifreq* ifr;
   for ( ifr = conf.ifc_req; (char*)ifr < (char*)conf.ifc_req + conf.ifc_len; ifr++ )
   {
      if ( ifr->ifr_addr.sa_data == (ifr+1)->ifr_addr.sa_data )
         continue;  // duplicate, skip it

      if ( ioctl( sock, SIOCGIFFLAGS, ifr ))
         continue;  // failed to get flags, skip it
      if ( ioctl( sock, SIOCGIFHWADDR, ifr ) == 0 )
      {
         if ( !foundMac1 )
         {
            foundMac1 = true;
            mac1 = hashMacAddress( (unsigned char*)&(ifr->ifr_addr.sa_data));
         } else {
            mac2 = hashMacAddress( (unsigned char*)&(ifr->ifr_addr.sa_data));
            break;
         }
      }
   }

   close( sock );

#endif // !DARWIN

   // sort the mac addresses. We don't want to invalidate
   // both macs if they just change order.
   if ( mac1 > mac2 )
   {
      unsigned short tmp = mac2;
      mac2 = mac1;
      mac1 = tmp;
   }
}

unsigned short getVolumeHash()
{
   // we don't have a 'volume serial number' like on windows. Lets hash the system name instead.
   unsigned char* sysname = (unsigned char*)getMachineName();
   unsigned short hash = 0;

   for ( unsigned int i = 0; sysname[i]; i++ )
      hash += ( sysname[i] << (( i & 1 ) * 8 ));

   return hash;
}

#ifdef DARWIN
 #include <mach-o/arch.h>
 unsigned short getCpuHash()
 {
     const NXArchInfo* info = NXGetLocalArchInfo();
     unsigned short val = 0;
     val += (unsigned short)info->cputype;
     val += (unsigned short)info->cpusubtype;
     return val;
 }

#else // !DARWIN

 static void getCpuid( unsigned int* p, unsigned int ax )
 {
    __asm __volatile
    (   "movl %%ebx, %%esi\n\t"
        "cpuid\n\t"
        "xchgl %%ebx, %%esi"
        : "=a" (p[0]), "=S" (p[1]),
          "=c" (p[2]), "=d" (p[3])
        : "0" (ax)
    );
 }

 unsigned short getCpuHash()
 {
    unsigned int cpuinfo[4] = { 0, 0, 0, 0 };
    getCpuid( cpuinfo, 0 );
    unsigned short hash = 0;
    unsigned int* ptr = (&cpuinfo[0]);
    for ( unsigned int i = 0; i < 4; i++ )
       hash += (ptr[i] & 0xFFFF) + ( ptr[i] >> 16 );

    return hash;
 }
#endif // !DARWIN

int main()
{

  printf("Machine: %s\n", getMachineName());
  printf("CPU: %d\n", getCpuHash());
  printf("Volume: %d\n", getVolumeHash());
  return 0;
}

这篇关于如何以跨平台的方式获取(几乎)唯一的系统标识符?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-31 16:41