Программирование Socket C: Попытка обслужить новые клиентские соединения, используя fork () - PullRequest
0 голосов
/ 19 октября 2019

Таким образом, каждое клиентское соединение должно обслуживаться новым дочерним процессом.

Прямо сейчас у меня есть функция generate_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;
}

ПРОБЛЕМА: Для каждого соединения, использующего fork (), дочерний процесс копируется из родительского и, как вы можете видеть в реализации ниже, клиентский объект стот же идентификатор клиента копируется в дочерний процесс (по крайней мере, я так думаю).

Например: при подключении к серверу с помощью терминала 1 создается идентификатор клиента 83, а терминала2 connection также отправляет идентификатор 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");
           }
       }
}

Я думаю, что проблема связана с client_t client = generate_client(); внутри fork () .., который генерирует клиент, скопированный из родительскогопроцесс, как я могу повторно вызвать это в каждом процессе, может быть?

1 Ответ

0 голосов
/ 19 октября 2019

Это похоже на вопрос, опубликованный всего несколько часов назад: Попытка fork () после нового подключения клиента к серверу [Программирование на сокете C]

Краткий ответ:

Функция 'rand' использует скрытое 'состояние' для генерации следующего случайного числа. Поскольку родитель никогда не использует rand, каждый разветвленный потомок получит одинаковое состояние и сгенерирует одинаковую последовательность случайных чисел.

Несколько возможных исправлений:

  • Сделайте один вызов randв родительском (ДО разветвления). Это приведет к тому, что каждый дочерний элемент будет начинаться с разного состояния.
  • Вызвать rand в родительском элементе перед ветвью и сохранить идентификатор для дочернего элемента.
  • Настройка произвольного просмотра для каждого дочернего элемента,используя srand.
...