【问题标题】:Trying to fork() after new client connection to server [Socket Programming C]在新客户端连接到服务器后尝试 fork() [套接字编程 C]
【发布时间】:2020-02-14 23:53:57
【问题描述】:

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

当建立连接时,服务器应该为每个新客户端返回一个随机数 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));
}

【问题讨论】:

    标签: c sockets ubuntu server fork


    【解决方案1】:

    “rand”函数使用隐藏的“状态”来生成下一个随机数。由于 parent 从不使用 rand,因此每个分叉的 child 将获得相同的状态,并会生成相同的随机数序列。

    一些可能的修复:

    • 在父节点中调用 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) ;
    

    【讨论】:

      【解决方案2】:

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

      srand() 函数使用参数作为新的伪随机数序列的种子,这些伪随机数将由后续调用 rand() 返回。如果随后使用相同的种子值调用 srand(),则应重复伪随机数序列。如果在调用 srand() 之前调用了 rand(),则应生成与第一次调用 srand() 时相同的序列,种子值为 1。

      要么打电话给srand,要么不打电话。如果您不呼叫srand,则与您呼叫srand(1) 相同。所以这两种情况的逻辑是一样的。

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-08
        • 2019-03-17
        • 1970-01-01
        • 1970-01-01
        • 2016-02-09
        • 1970-01-01
        相关资源
        最近更新 更多