问题
So I have a server that is supposed to create a new process for every new connection to the server. Therefore I will have multiple clients connecting to one server.
When a connection is made the server should return a random number id for each new client.
PROBLEM: the server is printing the same random number id for all the clients (terminals) connecting to the server.
What should happen: child process should generate (rand()) id for a new unique client connection. Proving each new client is being connected to the server. Is my fork correct?
while (1)
{
pid_t childpid; /* variable to store child's process id */
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if ((childpid = fork()) == -1)
{ // fork failed.
close(new_fd);
continue;
}
else if (childpid > 0)
{ // parent process
printf("\n parent process\n");
}
else if (childpid == 0)
{ // child process
printf("\n child process\n");
printf("\n random num: %d\n", rand()); -----> Testing, should be unique for each client (its not!)
/* ***Server-Client Connected*** */
client_t client = generate_client();
}
printf("server: got connection from %s\n",
inet_ntoa(their_addr.sin_addr));
}
回答1:
The 'rand' function uses a hidden 'state' to generate the next random number. Since the parent never uses rand, each forked child will get the same state, and will generate the same sequence of random number.
Few possible fixes:
- Make one call to rand in the parent (BEFORE forking). This will result in each child starting with different state.
- Call rand in the parent, before the fork, and save the id for the child to use.
- Setup random see for each child, using srand.
int child_id = rand() ;
if ((childpid = fork()) == -1)
{ // fork failed.
close(new_fd);
continue;
}
... Later in the child.
printf("random num: %d", child_id) ;
回答2:
You should read the documentation for rand
, particularly this part:
The srand() function uses the argument as a seed for a new sequence of pseudo-random numbers to be returned by subsequent calls to rand(). If srand() is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated. If rand() is called before any calls to srand() are made, the same sequence shall be generated as when srand() is first called with a seed value of 1.
Either you call srand
or you don't. If you don't call srand
, it's the same as if you called srand(1)
. So the logic is the same in both cases.
If the two processes generated different numbers, then the requirements for rand
would be violated. As the documentation says, "If srand() is then called with the same seed value, the sequence of pseudo-random numbers shall be repeated." Both of your processes called srand
with the same value (possibly, implicitly 1), so they must both produce the same sequence.
I would strongly suggest you to simply not ever use rand
or srand
. Just use functions that have the semantics you require. If you need random numbers that are different in both processes, write a function to produce that. Another option is to do something like srand(getpid() ^ (time(NULL)<<8))
after fork
.
来源:https://stackoverflow.com/questions/58443143/trying-to-fork-after-new-client-connection-to-server-socket-programming-c