简体   繁体   中英

C Socket Programming: Trying to serve new client connections using fork()

So each client connection is to be served on a new child process.

Right now, I have a function generate_client() that creates a client and gives it a random id number (that is returned to client).

client_t generate_client()
{
    client_t *client = malloc(sizeof(client_t));

    client->clientID = randomClientIdGenerator(); < ----
    client->entryIndexConstant = 0;
    client->messageQueueIndex = 0;
    client->readMsg = 0;
    client->totalMessageSent = 0;
    client->unReadMsg = 0;
    client->status = CLIENT_INACTIVE;

    return *client;
}

int randomClientIdGenerator()
{
    int num = rand() % MAX_CLIENTS;
    return num;
}

PROBLEM: For each connection using fork(), the child process is copied over from parent and as you can see in the implementation below the client object with the same client id is copied over to the child process (at least this is what I think is happening).

For example: connecting to server using terminal 1 generates client id 83, and terminal 2 connection also sends id 83.

    /* bind the socket to the end point */
    if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
    {
        perror("bind");
        exit(1);
    }

    /* start listnening */
    if (listen(sockfd, BACKLOG) == -1)
    {
        perror("listen");
        exit(1);
    }

    while (1)
    {

        sin_size = sizeof(struct sockaddr_in);
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
        if (new_fd == -1)
        {
            perror("accept.");
            printf("\n...error: accept new_fd failed\n");
            // continue;
        }

        printf("server: got connection from %s\n",
               inet_ntoa(their_addr.sin_addr));

        if (!fork())
        { /* this is the child process */
            printf("\n-----------------------CHILD START ----------\n");

            printf("\n child process id is %d. parent id is: %d\n", getpid(), getppid());

            /* ***Server-Client Connected*** */
            client_t client = generate_client();

            printf("\n =>client id %d STATUS: %d\n", client.clientID, client.status);

             if (client.clientID < -1)
            {
                perror("SERVER: failed to create client object (Max. 100 clients allowed)");
                printf("SERVER: failed to create client object (Max. 100 clients allowed) \n");
                exit(1);
                // send response to client Cant accept connection
            }

            // Send: Welcome Message.   ------------> SAME id of 83 is given to child process!!!
            if (send(new_fd, &client.clientID, sizeof(int), 0) == -1)
            {
                perror("send");
                printf("Error: Welcome message not sent to client \n");
           }
       }
}

I think the problem is with client_t client = generate_client(); inside fork().. which generates the client that is copied over from parent process, how do I re-call this in each process maybe?

This seems to be identical of a question posted just few hours ago: Trying to fork() after new client connection to server [Socket Programming C]

Short answer:

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM