Problema de compatibilitate GUID/UUID între .NET și Linux

În programul meu de tip C ++, generez o valoare uuid folosind pachetul uuid al liniei debian, îmi întoarce o matrice de caractere nesemnată de mărimea 16, care este de tip uuid_t. Apoi o convertesc la șir și o tipăresc în consola.

Apoi, iau aceeași matrice de octeți și o trimit la o mașină de ferestre prin rețea. Mașina Windows utilizează tipul GUID al .net și creează un obiect GUID utilizând aceeași matrice octet. Apoi folosesc metoda ToString a GUID pentru al imprima din nou la consola. Surprinzător aceeași matrice octet are reprezentări diferite de șir sub Linux și .Net, chiar dacă ele sunt aproape similare.

Iată un exemplu:

Byte array:

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

Așa cum ați putea observa că sunt foarte asemănătoare, ultimele părți sunt aceleași, primele părți folosesc aceleași cifre, doar ordinea cifrelor este diferită. Fiecare UUID pe care l-am creat așa cum am explicat mai sus urmează același model care mă face să cred că există o diferență de ordin octet.

Cum pot crea o valoare UUID în linux și am aceeași reprezentare de șir folosind aceeași matrice octet.

1
Ok omitem partea de rețea, am introdus manual aceeași matrice octet într-o aplicație de mici dimensiuni .net, încă nu are aceeași reprezentare de primăvară. Am inversat ordinea octeților, nu generează nimic semnificativ. prin urmare, nu arata ca Htons este vinovatul aici.
adăugat autor erin c, sursa
din înțelegerea mea dacă doriți să aveți aceeași reprezentare a șirului între .net și linux, va trebui să modificați ordinea octeților după cum urmează. Ordinea inițială a indexurilor generate în linux: 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16 ordinea pe care ar trebui să o utilizați în .net: 4,3,2,1,6,5,8,7,9,10,11,12,13,14,15,16, care vor da același șir.
adăugat autor erin c, sursa
După ce am verificat un pic mai mult, am înțeles că este o problemă endianness cum ați spus la început, GUID constă din 4 octeți int, 2 octeți scurți, 2 octeți scurți, 8 1 octeți, mașina mea linux convertește 4 octeți și 2 octeți în ordinul mic endian.
adăugat autor erin c, sursa
nope ieșirea mea linux a fost greșit, anumite porțiuni de uuid mazăre de byte a fost în ordine mic octet endian. și anume primii 8 octeți ai matricei (0-3 (4 octeți), 4-5 (2 octeți), 6-7 (2 octeți) care a creat diferența. Dacă convertiți fiecare porțiune în endian mare înainte de a le converti în șir, veți avea același rezultat în linux și .net
adăugat autor erin c, sursa
Eu folosesc uuid_unparse (uuidGenerated, p_pGeneratedUUID); pentru a obține o matrice de caractere de tip uuid_t. apoi folosesc printf pentru a ieși.
adăugat autor erin c, sursa
Problema endianității? Nu ați uitat să sunați htons / ntohs ?
adăugat autor Vlad, sursa
În conformitate cu wiki: GUID , GUID-urile trebuie să fie codificate ca Big-Endian.
adăugat autor Vlad, sursa
Dacă nu mă înșel, aceasta înseamnă că ieșirea linux este corectă. Cum scoateți GUID-ul în .net?
adăugat autor Vlad, sursa
Hmm, atunci cum de a ieși guid în linux?
adăugat autor Vlad, sursa

2 răspunsuri

În conformitate cu acest și mesajele , problema este cu adevărat în înțelegerea diferită a faptului dacă GUID-urile/UUID-urile ar trebui fi Big- sau Little-Endian. Se pare că implementarea Microsoft le tratează ca Big-Endian (cel puțin pe platformele Intel), dar uuid_unparse pare a fi Little-Endian. Wiki spune că GUID (care este UUID-ul Microsoft) urmează RFC 4122, secțiunea 4.1.2 , care pare să ceară o comandare Big-Endian.

Deci, aceasta este o incoerență clară între implementări. Ca soluție, aș propune schimbul de date între sistemele în format de șir, care pare să fie consecvent în ambele sisteme.

2
adăugat

Din păcate, nu puteți avea aceeași matrice de byte și avea Guid.ToString să producă un șir care să se potrivească cu șirul Linux.

Va trebui să decideți pe care doriți să acordați prioritate:

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);
    }
}
0
adăugat