Como a semente de printf() para evitar a colisão em um grande número de máquinas?

StackOverflow https://stackoverflow.com//questions/21020418

  •  21-12-2019
  •  | 
  •  

Pergunta

Normalmente, a propagação de printf() é feita por:

srand(time(NULL));

No meu caso, eu uso de números aleatórios para gerar um identificador para o meu processo de cliente em tempo de execução na rede.O processo às vezes é reiniciado e gera um novo identificador.Como o número de clientes aumenta, há uma boa chance de que dois clientes de chamada srand(time(NULL)) dentro do mesmo segundo, o que cria dois idênticos identificadores, ou uma colisão, como visto pelo lado do servidor. Algumas pessoas sugeriram uma resolução mais fina:

srand((time.tv_sec * 1000) + (time.tv_usec / 1000));

Mas O problema aqui é que a semente irá se repetir a cada 24 dias, mais ou menos, e quando o número de máquinas é grande o suficiente, ainda há uma chance de colisão. Não há outra solução:

srand(time.tv_usec * time.tv_sec);

Mas isso parece problemático para mim, também, porque o módulo do produto (o maior de bits de excesso e obter abandonada), não está uniformemente distribuído dentro do intervalo de unsigned int valor da semente.Por exemplo, para cada s, time.tv_usec == 0 leva a mesma semente.

Assim é que existe uma forma de semente de printf() no meu caso?

Editar:o cliente é executado em Linux, Windows, Android e iOS, por isso, /dev/random ou /dev/urandom não está sempre disponível.

P. S.Eu estou ciente de que o GUID/UUID abordagem, mas eu gostaria de saber se é possível apenas de semente de printf() corretamente neste caso.

Foi útil?

Solução

Você tem dois domínios: clientes e processos.Portanto, você precisa de um identificador exclusivo para cada um.Os processos obviamente podem ser feitos com o processo de processo.Para clientes, sugiro usar o endereço MAC, que deve ser exclusivo para cada interface de rede.Acredito que todas as plataformas que você lista soquetes de suporte, portanto, o IOCTL Siocgifhwaddr pode ser suportado.

O único problema é que os endereços MAC são 48 bits e os PIDs são tipicamente 32 bits, então você tem que escolher os bits de entropia mais altos dos dois valores a serem usados para sua semente SRAND.Eu sugiro os 16 bits inferiores do PID e os 16 bits inferiores do endereço MAC.

Outras dicas

srand e rand simplesmente não é adequado se você tem um monte de processos ou threads que precisam ter pseudo-aleatoriedade que é independente entre eles.

Em sistemas POSIX você pode usar o rand48 família de funções como jrand48 que tenham conhecido o tamanho do estado.Se depender do processo, thread e máquina de independência, você deve usar bits mais significativos do processo de ID, ID de thread, endereço IP e tempo para inicializar o estado. jrand[48] demora (e modifica) um estado de três short, então ele deve ser relativamente simples, a semente destes com os diferentes quantities.

Todos, mas um dos sistemas que são POSIX, que deve trabalhar lá.O que seria adequado a um fallback para sistemas Windows, eu não sei.

Se dois geradores de números aleatórios nunca tiverem colisões, eles não são aleatórios.Seria como jogar 'Snap', mas nunca recebendo uma partida.

Então, o que você quer é pior, em vez de um melhor gerador de números aleatórios.Usar GUIDs é de fato uma abordagem que deve remover inteiramente o problema para você.

Mas, se você está feliz apenas reduzindo a chance de colisões, em vez de eliminá-los inteiramente, você poderia usar o endereço IP IP da máquina (ou número de série do processador, ou somesuch) como parte da semente.

Se você está escrevendo para a plataforma linux, use /dev/random e /dev/urandom para obter números aleatórios.Ao contrário de srand(), /dev/random e /dev/urandom usa o ruído gerado a partir de periféricos de hardware para gerar números aleatórios. srand() usa semente fornecido como argumento para gerar números aleatórios.

Eu acho que você estará interessado no papel "Números aleatórios paralelos: tão fácil quanto 1, 2, 3".

citando do resumo: "Todos os nossos PRNGs passam rigorosos testes estatísticos (incluindo o Bigcrush de Testu01) e produzem pelo menos 264 fluxos paralelos exclusivos de números aleatórios, cada um com o período 2128 ou mais"

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top