Попытка fork () после нового подключения клиента к серверу [Socket Programming C] - PullRequest
0 голосов
/ 18 октября 2019

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

Когда соединение установлено, сервер должен возвращать случайный номер для каждого нового клиента.

ПРОБЛЕМА: сервер печатаетодин и тот же случайный номер для всех клиентов (терминалов), подключающихся к серверу.

Что должно произойти: дочерний процесс должен сгенерировать (rand ()) идентификатор для нового уникального клиентского соединения. Проверка каждого нового клиента подключается к серверу. Моя вилка верна?

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));
}

Ответы [ 2 ]

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

Вы должны прочитать документацию для rand, особенно этой части:

Функция srand () использует аргумент в качестве начального числа для новой последовательности псевдослучайных чисел, которые должны быть возвращеныпоследующие вызовы rand (). Если затем вызывается srand () с тем же начальным значением, последовательность псевдослучайных чисел должна повторяться. Если rand () вызывается до того, как будут выполнены какие-либо вызовы srand (), генерируется та же последовательность, что и при первом вызове srand () со начальным значением 1.

Либо вы вызываете srand или нет. Если вы не позвоните srand, это так же, как если бы вы позвонили srand(1). Таким образом, логика одинакова в обоих случаях.

Если два процесса генерируют разные числа, то требования для rand будут нарушены. Как сказано в документации: «Если затем вызывается srand () с тем же начальным значением, последовательность псевдослучайных чисел должна повторяться». Оба ваших процесса называются srand с одним и тем же значением (возможно, неявно 1), поэтому они должны оба выдают одну и ту же последовательность.

Я бы настоятельно рекомендовал вам просто никогда не использоватьrand или srand. Просто используйте функции, которые имеют семантику, которая вам требуется. Если вам нужны случайные числа, которые различны в обоих процессах, напишите функцию для их получения. Другой вариант - сделать что-то вроде srand(getpid() ^ (time(NULL)<<8)) после fork.

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

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

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

  • Сделайте один вызов randв родительском (ДО разветвления). Это приведет к тому, что каждый дочерний элемент будет начинаться с разного состояния.
  • Вызвать rand в родительском элементе перед вилкой и сохранить идентификатор для дочернего элемента.
  • Настройка произвольного просмотра для каждого дочернего элемента,используя 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) ;
...