【问题标题】:GUID/UUID compatibility issue between .NET and Linux.NET 和 Linux 之间的 GUID/UUID 兼容性问题
【发布时间】:2012-06-01 12:15:53
【问题描述】:

在我的 c++ 程序中,我正在使用 debian linux 的 uuid 包生成一个 uuid 值,它返回给我一个大小为 16 的无符号字符数组,它的类型为 uuid_t。然后我将其转换为字符串并将其打印到控制台。

然后我将相同的字节数组通过网络发送到 Windows 机器。 Windows 机器使用 .net 的 GUID 类型,并使用相同的字节数组创建 GUID 对象。然后我使用 GUID 的 ToString 方法再次将其打印到控制台。令人惊讶的是,相同的字节数组在 Linux 和 .Net 下具有不同的字符串表示形式,尽管它们几乎相似。

这是一个例子:

字节数组:

101,208,176,173,236,192,64,86,191,214,132,2,213,232,143,247

Linux: 65d0b0ad-ecc0-4056-bfd6-8402d5e88ff7

.NET: adb0d065-c0ec-5640-bfd6-8402d5e88ff7

您可能会注意到它们非常相似,最后一部分是相同的,第一部分使用相同的数字,只是数字的顺序不同。我按照上面解释的方式创建的每个 UUID 都遵循相同的模式,这让我认为存在字节顺序差异。

如何在 linux 中创建一个 UUID 值并使用相同的字节数组具有相同的字符串表示。

【问题讨论】:

  • 字节序问题?你不是忘了打htons/ntohs吗?
  • 好吧,我省略了网络部分,我在一个小的.net应用程序中手动输入了相同的字节数组,它仍然没有相同的弹簧表示。我颠倒了字节顺序,它不会产生任何有意义的东西。因此看起来 htons 不是这里的罪魁祸首。
  • 据我了解,如果您想在 .net 和 linux 之间使用相同的字符串表示形式,则需要按如下方式更改字节顺序。在 linux 中生成的索引的原始顺序:1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 您应该在 .net 中使用的顺序: 4,3,2,1,6,5,8,7,9,10,11,12,13,14,15,16,这将产生相同的字符串。
  • 再查了一下,我明白是你一开始说的字节序问题,GUID由4字节int,2字节短,2字节短,8个1字节组成,我的linux机器正在以 little endian 顺序转换 4 个字节和 2 个字节。
  • 根据wiki:GUID,GUID 必须编码为 Big-Endian。

标签: c++ .net linux guid uuid


【解决方案1】:

根据thisthis 消息,问题实际上在于对GUID/UUID 应该是Big-Endian 还是Little-Endian 的不同理解。看起来微软的实现将它们视为大端(至少在英特尔平台上),但uuid_unparse 似乎是小端。 Wiki 表示 GUID(即 Microsoft 的 UUID)遵循 RFC 4122, section 4.1.2,这似乎需要 Big-Endian 排序。

因此,这显然是实现之间的不一致。作为一种解决方法,我建议以字符串格式在系统之间交换数据,这在两个系统之间似乎是一致的。

【讨论】:

    【解决方案2】:

    很遗憾,您不能使用相同的字节数组Guid.ToString 生成与 Linux 字符串匹配的字符串。

    您需要决定优先考虑哪一个:

    var dotNetGuid = new Guid(new byte[] { 101, 208, 176, 173, 236, 192, 64, 86,
                                           191, 214, 132, 2, 213, 232, 143, 247 });
    
    // option 1 - keep the existing guid's byte array intact
    //            and create a new ToUnixString method to display it as-required
    
    Console.WriteLine(dotNetGuid.ToString());      // adb0d065-c0ec-5640-bfd6-8402d5e88ff7
    Console.WriteLine(dotNetGuid.ToUnixString());  // 65d0b0ad-ecc0-4056-bfd6-8402d5e88ff7
    
    // option 2 - create a new guid by re-arranging the existing guid's byte array
    //            and then use the standard ToString method
    
    var unixGuid = dotNetGuid.ChangeByteOrder();
    Console.WriteLine(dotNetGuid.ToString());  // adb0d065-c0ec-5640-bfd6-8402d5e88ff7
    Console.WriteLine(unixGuid.ToString());    // 65d0b0ad-ecc0-4056-bfd6-8402d5e88ff7
    
    // ...
    
    public static class GuidExtensions
    {
        public static string ToUnixString(this Guid guid,
            string format = "D", IFormatProvider provider = null)
        {
            return guid.ChangeByteOrder().ToString(format, provider);
        }
    
        public static Guid ChangeByteOrder(this Guid guid)
        {
            var s = guid.ToByteArray();
            var d = new byte[]
                        {
                            s[3], s[2], s[1], s[0], s[5], s[4], s[7], s[6],
                            s[8], s[9], s[10], s[11], s[12], s[13], s[14], s[15]
                        };
    
            return new Guid(d);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多