This article解释了如何生成Guids。
我的问题是,有什么方法可以找出我的网站中哪台机器生成了这个Guid以及何时生成?
答案 0 :(得分:13)
Neil Fenwick是对的。但是,我们可以利用这种结构。
版本4 (。Net)
版本4 UUID使用仅依赖于随机数的方案。该算法设置版本号以及两个保留位。使用随机或伪随机数据源设置所有其他位。版本4 UUID具有xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx形式,其中x是任何十六进制数字,y是8,9,A或B中的一个。 f47ac10b-58cc-4372-a567-0e02b2c3d479。
使用版本字段
我们可以自由地改变字节8的第一个半字节;因此,如果您的机器少于17台,您可以通过更改在每台机器上创建的GUID来识别它们。
static Guid NewSystemGuid(int machine)
{
if (machine < 0 | machine > 0xF)
throw new ArgumentOutOfRangeException("machine");
var g = Guid.NewGuid();
var arr = g.ToByteArray();
arr[7] = (byte)((machine << 4) | (arr[7] & 0xF));
return new Guid(arr);
}
static int ExtractMachine(Guid guid)
{
var arr = guid.ToByteArray();
return (arr[7] >> 4) & 0xF;
}
使用版本字段和'y'
我不确定更改Y是否会改变GUID的唯一性,因此您的里程可能会有所不同。如果少于17台机器坚持使用第一种解决方案。
static Guid NewSystemGuid(int machine)
{
if (machine < 0 | machine > 0xFF)
throw new ArgumentOutOfRangeException("machine");
var m1 = machine & 0xF;
var m2 = (machine >> 4) & 0xF;
var g = Guid.NewGuid();
var arr = g.ToByteArray();
arr[7] = (byte)((m1 << 4) | (arr[7] & 0xF));
arr[8] = (byte)((m2 << 4) | (arr[8] & 0xF));
return new Guid(arr);
}
static int ExtractMachine(Guid guid)
{
var arr = guid.ToByteArray();
return
((arr[7] >> 4) & 0xF) |
(((arr[8] >> 4) & 0xF) << 4);
}
使用版本和'y'(Redux)
您仍然可以通过将机器数量限制为63来保留'y'中的值(使用最后2位代表'y'的4个可能值):
static Guid NewSystemGuid(int machine)
{
if (machine < 0 | machine > 0x3F)
throw new ArgumentOutOfRangeException("machine");
var m1 = machine & 0xF;
var m2 = (machine >> 4) & 0xF;
var g = Guid.NewGuid();
var arr = g.ToByteArray();
arr[7] = (byte)((m1 << 4) | (arr[7] & 0xF));
var y = (arr[8] >> 4) & 0xF;
switch (y)
{
case 0x8:
arr[8] = (byte)((m2 << 4) | (arr[8] & 0xF));
break;
case 0x9:
arr[8] = (byte)(((m2 | 0x8) << 4) | (arr[8] & 0xF));
break;
case 0xA:
arr[8] = (byte)(((m2 | 0x4) << 4) | (arr[8] & 0xF));
break;
case 0xB:
arr[8] = (byte)(((m2 | 0xC) << 4) | (arr[8] & 0xF));
break;
default:
throw new Exception();
}
return new Guid(arr);
}
static int ExtractMachine(Guid guid)
{
var arr = guid.ToByteArray();
return
((arr[7] >> 4) & 0xF) |
(((arr[8] >> 4) & 0x3) << 4);
}
使用版本1 GUID
您也可以使用版本1 GUID,因为它仍然可以生成它们:
class SequentialGuid
{
[DllImport("rpcrt4.dll", SetLastError = true)]
static extern int UuidCreateSequential(out Guid guid);
public static Guid NewGuid()
{
Guid guid;
UuidCreateSequential(out guid);
return guid;
}
public static byte[] ExtractMacAddress(Guid guid)
{
var arr = guid.ToByteArray();
// Require version 1.
if (((arr[7] >> 4) & 0xF) != 1)
throw new ArgumentOutOfRangeException("guid", "GUID is required to be a sequential (version 1) GUID.");
var macLong = BitConverter.ToInt64(arr, arr.Length - 8);
macLong = IPAddress.NetworkToHostOrder(macLong);
arr = BitConverter.GetBytes(macLong);
Array.Resize(ref arr, 6);
return arr;
}
}