方法一:
Linux平台利用dev/urandom来生成随机数,再转成字符串。
dev/random和/dev/urandom是Linux系统中提供的随机伪设备,这两个设备的任务,是提供永不为空的随机字节数据流。很多解密程序与安全应用程序(如SSH Keys,SSL Keys等)需要它们提供的随机数据流。
以下代码生成的字符串长度为两倍len.
#include"log_uuid.h"
#include <stdlib.h>
#include <unistd.h>
#include<fcntl.h>
std::string getUUID(unsigned int len) {
std::string str;
unsigned char* buffer = new unsigned char[len+1];
char* uuid = new char [2*len+1];
int fd = open("/dev/urandom", O_RDONLY);
if (read(fd, buffer, len) == len) {
for(int i=0;i<len;i++)
sprintf(uuid+i*2, "%02X",buffer[i]);
uuid[2*len] = '\0';
str = uuid;
} else {
printf("Error: GetUnique %d\n", __LINE__);
}
delete [] buffer;
delete [] uuid;
return str;
}
使用/dev/urandom生成uuid这种方法的一个应用案例就是在Redis 分布式锁redlock算法.redlock算法中,客户端加锁前需要生成一个uuid作为签名。
I assume it’s 20 bytes from /dev/urandom, but you can find cheaper ways to make it unique enough for your tasks.
Redis官方建议通过/dev/urandom生成20字节的uuid,但是也可以使用其它一些代价更低的算法来实现,只要能够满足需求就行。以下是Redis官方推荐的redlock C++实现,此处代码做了一些细小的改动。
sds CRedLock::GetUniqueLockId() {
unsigned char buffer[20];
// open rand file
m_fd = open("/dev/urandom", O_RDONLY);
if (read(m_fd, buffer, sizeof(buffer)) == sizeof(buffer)) {
//获取20byte的随机数据
sds s;
s = sdsempty();
for (int i = 0; i < 20; i++) {
s = sdscatprintf(s, "%02X", buffer[i]);
}
return s;
} else {
//读取失败
printf("Error: GetUniqueLockId %d\n", __LINE__);
}
return NULL;
}
在项目中可能需要生成一些随机字符串来作为测试用例,可以用另一种方法来生成实现,这种方法更加快捷,虽然随机性差一些但是已经够用了。
另一方法,生成最大长度为maxlen的随机长度的随机字符串
std::string randstr(int max_len)
{
int real_len = rand() % max_len;
if(real_len == 0) return "";
char* str = (char*)malloc(real_len);
for (int i = 0; i < real_len; ++i)
{
switch ((rand() % 3))
{
case 1:
str[i] = 'A' + rand() % 26;
break;
case 2:
str[i] = 'a' + rand() % 26;
break;
default:
str[i] = '0' + rand() % 10;
break;
}
}
str[real_len -1] = '\0';
std::string string = str;
free(str);
return string;
}