如何用C语言生成GUID?

发布于 2024-12-04 04:59:41 字数 349 浏览 0 评论 0原文

我想生成插入 SQLite 数据库的 guid(即数据库本身不支持)。但是,我想控制某些属性:

  1. 用于生成增加的 guid 值的有序性。
  2. 计算机独立性。数据库是公共的,可能/可能不希望 guid 允许某人将数据追溯到特定机器。
  3. “足够”的随机性。 guid 是数据库中的键,它将与许多其他数据库合并,并且可能变得相当大,这意味着像许多算法那样伪造 guid 是不好的。
  4. 我可以使用系统特定的 API 来处理,但请链接 Windows 和 Linux 函数,并且首选 SQLite 之类的东西,我可以在其中使用其他人编写的代码。
  5. 我还更喜欢可以在商业应用程序中使用的代码。

I want to generate guids to insert into a SQLite database (i.e. no support from the db itself). However, I would like to have control over certain properties:

  1. Orderedness for generating increasing guid values.
  2. Computer independence. The db is public and may/may not want guids to allow someone to trace data back to a specific machine.
  3. 'Enough' randomness. The guids are keys in the db which is going to be merged with a lot of other dbs and can get quite large, meaning that faking a guid like many algorithms do is no good.
  4. I can deal with using system specific APIs but please link both Windows and Linux functions, and something like SQLite is preferred, where I can just use code someone else wrote.
  5. I would also prefer code which is OK to use in a commercial application.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

清欢 2024-12-11 04:59:41

寻找创建包含作者正在寻找的许多元素的 GUID 答案的一个地方是 PHP .. https://www.php.net/uniqid .. 在他们的示例中,他们讨论了如何将服务器名称、数据库名称和其他元素添加到 GUID。

但是,为了满足基于 C 的 GUID 函数的需求,这里是基于 JavaScript 函数的代码.. 如何创建 GUID / UUID? .. 此示例使用 RegEx 创建 GUID。

下面的代码将基于 JavaSCript 示例创建 GUID。我确信还有更优雅的解决方案。这是一些拼凑在一起的东西,有助于为其他人提供一个清晰的榜样。

srand (clock());
char GUID[40];
int t = 0;
char *szTemp = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
char *szHex = "0123456789ABCDEF-";
int nLen = strlen (szTemp);

for (t=0; t<nLen+1; t++)
{
    int r = rand () % 16;
    char c = ' ';   
    
    switch (szTemp[t])
    {
        case 'x' : { c = szHex [r]; } break;
        case 'y' : { c = szHex [r & 0x03 | 0x08]; } break;
        case '-' : { c = '-'; } break;
        case '4' : { c = '4'; } break;
    }
    
    GUID[t] = ( t < nLen ) ? c : 0x00;
}

printf ("%s\r\n", GUID);

注意:字符串以 0x00 字符结尾。

One place to look for an answer to creating a GUID that contains many of the elements the author is looking for is in PHP .. https://www.php.net/uniqid .. In their examples, they discuss how to add server names, database names, and other elements to a GUID.

However, to address the need for a C based GUID function, here is code based on a JavaScript function .. How do I create a GUID / UUID? .. this example uses RegEx to create the GUID.

Below is code that will create a GUID based on the JavaSCript example. I'm sure there are more elegant solutions out there. This is something cobbled together to help give a clean example for others to follow.

srand (clock());
char GUID[40];
int t = 0;
char *szTemp = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx";
char *szHex = "0123456789ABCDEF-";
int nLen = strlen (szTemp);

for (t=0; t<nLen+1; t++)
{
    int r = rand () % 16;
    char c = ' ';   
    
    switch (szTemp[t])
    {
        case 'x' : { c = szHex [r]; } break;
        case 'y' : { c = szHex [r & 0x03 | 0x08]; } break;
        case '-' : { c = '-'; } break;
        case '4' : { c = '4'; } break;
    }
    
    GUID[t] = ( t < nLen ) ? c : 0x00;
}

printf ("%s\r\n", GUID);

Note: strings end with a 0x00 character.

凉风有信 2024-12-11 04:59:41

您可以使用或查看 Boost.Uuid 的代码:

http://www.boost.org/doc/libs/1_47_0/libs/uuid/index.html

它是一个 C++ 库,但仍然可以在里面找到代码作者在多个系统上检索了 Uuid。上次我检查时(2010 年 1 月),我至少发现了 Windows 和 Linux/Solaris 的以下实现(此信息可能已过时):

Linux/Solaris 上的 UUID/GUID

打开文件到 /dev/urandom 并读取足够的字节 (16) 来组成 GUID/UUID。

Windows 上的 UUID/GUID

使用以下 WinAPI 函数

其他实现

关于 GUID/UUID 的维基百科页面有一个可供选择的实现列表使用/研究:

https://en.wikipedia.org/wiki/UUID#Implementations

关于您的条件

有一个 GUID/UUID 类型始终是随机的(版本 4),表示与其他 GUID 兼容/UUID 语义,你应该尊重它。

现在,您希望及时订购 GUID/UUID。在不削弱 GUID/UUID 随机性的情况下做到这一点的唯一方法是在 16 字节 GUID/UUID 前面添加一个无符号整数(这将使您的标识符数据成为 20 字节或更多,具体取决于您的整数)。只需生成一个 GUID/UUID,并增加整数即可。

You can either use or look at the code of Boost.Uuid :

http://www.boost.org/doc/libs/1_47_0/libs/uuid/index.html

It is a C++ library, but still, you can find inside how the code author retrieved the Uuid on multiple systems. Last time I checked (january 2010), I found at least the following implementations for Windows and Linux/Solaris (this info could be outdated):

UUID/GUID on Linux/Solaris

Open a file to /dev/urandom and read enough bytes (16) to make up a GUID/UUID.

UUID/GUID on Windows

Use the following WinAPI functions

Other implementations

The Wikipedia page on GUID/UUID has a list of alternative implementations you could use/study:

https://en.wikipedia.org/wiki/UUID#Implementations

About your conditions

There is a GUID/UUID type which is always random (the version 4), meaning that to be compatible with other GUID/UUID semantics, you should respect that.

Now, you want the GUID/UUID to be ordered in time. The only way to do that without weakening the GUID/UUID randomness would be to prefix the 16-byte GUID/UUID with an unsigned integer (which would make your identifier data 20-bytes, or more, depending on your integer). Just generate a GUID/UUID, and increase the integer.

阳光下慵懒的猫 2024-12-11 04:59:41

首先,GUID 不是随机的,它们在数学上有很好的定义。

至于你的问题,将 GUID 创建作为存储过程放入数据库本身,这样系统就独立于平台。然后,使 GUID 成为以数据库 ID 为前缀的自动递增整数。该前缀允许轻松合并数据库。每个数据库的数据库 ID 必须是唯一的。如果您控制每个数据库,那么就很容易确保它们是唯一的。否则,您可能需要一个查找系统,将数据库 IP 地址(或其他一些唯一标识符)映射到唯一的数据库 ID。

如果您没有存储过程,则创建一个包含“NextIndex”和“DatabaseID”字段的表,并在添加新记录时更新它们:

read NextIndex and DatabaseID
increment NextIndex
ID = NextIndex + DatabaseID
add new record, setting "GUID" to the ID value

First off, GUIDs aren't random, they are very well defined mathmatically.

As for your problem, put the GUID creation into the database itself as a stored procedure, that way the system is platform independent. Then, make the GUID an auto-incrementing integer prefixed with a database ID. The prefix allows databases to be merged easily. The database ID needs to be unique for each database. If you control each database then it is straightforward to ensure these are unique. Otherwise you may need a lookup system which maps the database IP address (or some other unique identifier) to a unique database ID.

If you don't have stored procedures then create a table with "NextIndex" and "DatabaseID" fields and update them when a new record is added:

read NextIndex and DatabaseID
increment NextIndex
ID = NextIndex + DatabaseID
add new record, setting "GUID" to the ID value
葬シ愛 2024-12-11 04:59:41

这是一个 Linux 示例。 Linux 有一个用于 uuid 生成的头文件 uuid.h。对于我的 Ubuntu 20.x 操作系统,uuid.h 头文件位于 /usr/include/uuid/ 中。

/* uuid.c
 * 
 * Defines function uuid
 *
 * Print a universally unique identifer, created using Linux uuid_generate.
 *
 * 
 * Compile
 *
 * gcc uuid.c -o uuid -luuid -Wall -g
 *
 *
 * Run
 * 
 * ./uuid
 * 
 *
 * Debug
 *
 * gdb uuid
 * b main
 * r
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <uuid/uuid.h>

char* uuid(char out[UUID_STR_LEN]){
  uuid_t b;
  uuid_generate(b);
  uuid_unparse_lower(b, out);
  return out;
}

int main(){
  char out[UUID_STR_LEN]={0};
  puts(uuid(out));
  return EXIT_SUCCESS;
}

Here's a Linux example. Linux has a header file for uuid generation, uuid.h. For my Ubuntu 20.x OS, the uuid.h header file is in /usr/include/uuid/.

/* uuid.c
 * 
 * Defines function uuid
 *
 * Print a universally unique identifer, created using Linux uuid_generate.
 *
 * 
 * Compile
 *
 * gcc uuid.c -o uuid -luuid -Wall -g
 *
 *
 * Run
 * 
 * ./uuid
 * 
 *
 * Debug
 *
 * gdb uuid
 * b main
 * r
 *
 */

#include <stdlib.h>
#include <stdio.h>
#include <uuid/uuid.h>

char* uuid(char out[UUID_STR_LEN]){
  uuid_t b;
  uuid_generate(b);
  uuid_unparse_lower(b, out);
  return out;
}

int main(){
  char out[UUID_STR_LEN]={0};
  puts(uuid(out));
  return EXIT_SUCCESS;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文