在新的客户端连接到服务器后尝试fork()[套接字编程C]

时间:2019-10-18 02:31:31

标签: c sockets ubuntu server fork

因此,我有一台服务器,该服务器应该为与服务器的每个新连接创建一个新进程。因此,我将有多个客户端连接到一台服务器。

建立连接后,服务器应为每个新客户端返回一个随机数字ID。

问题:服务器正在为连接到服务器的所有客户端(终端)打印相同的随机数字ID。

会发生什么:子进程应为新的唯一客户端连接生成(rand())id。证明每个新客户端都已连接到服务器。我的叉子正确吗?

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 :(得分:0)

“ rand”函数使用隐藏的“ state”来生成下一个随机数。由于父母从未使用过兰德,所以每个分叉的孩子将获得相同的状态,并将生成相同的随机数序列。

一些可能的解决方法:

  • 在父级中向rand发出一个呼叫(在分叉之前)。这将导致每个孩子从不同的状态开始。
  • 在分叉之前在父级中调用rand,并保存ID供孩子使用。
  • 使用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) ;

答案 1 :(得分:0)

您应该阅读rand的文档,尤其是这一部分:

  

srand()函数使用该参数作为新的伪随机数序列的种子,该序列将由对rand()的后续调用返回。如果随后以相同的种子值调用srand(),则应重复伪随机数序列。如果在对srand()进行任何调用之前调用rand(),则将生成与种子值1首次调用srand()时相同的序列。

您打电话给srand,否则就不打电话。如果您不致电srand,则与您致电srand(1)相同。因此,两种情况下的逻辑都是相同的。

如果两个进程生成的数字不同,则将违反rand的要求。如文档所述,“如果以相同的种子值调用srand(),则应重复伪随机数的序列。”您的两个名为srand的进程都具有相同的值(可能隐式为1),因此它们必须都产生相同的序列。

我强烈建议您不要使用randsrand。只需使用具有所需语义的函数即可。如果您需要在两个过程中都不同的随机数,请编写一个函数来产生该随机数。另一种选择是在srand(getpid() ^ (time(NULL)<<8))之后执行类似fork的操作。