【问题标题】:How to set a TCP server timeout when accepting multiple client connections接受多个客户端连接时如何设置 TCP 服务器超时
【发布时间】:2019-10-05 09:10:34
【问题描述】:

我正在我的 TCP 服务器中处理一个函数,该函数在定义的时间段内接受预定数量的客户端连接(我现在将其设置为 10 秒),并在达到预定连接数时返回。我正在使用 select 函数使服务器超时,但由于某种原因,每次客户端加入时超时都会重置。例如,如果客户端在 5 秒后加入服务器,则超时重置并从 10 开始重新倒计时。非常感谢您的帮助,谢谢。

我正在使用 mac,我认为在这个操作系统上 FD_ISSET 用于检查客户端是否已连接(我很确定在 Linux 上不需要)。所以你可以像对待 linux 上 select 函数的返回值一样对待这个函数的返回值。

while (num_conn < NO_OF_CLIENTS) {

    // Listen for clients
    err = listen(server_fd, 128);
    if (err < 0) {
        fprintf(stderr, "Could not listen on socket\n");
        exit(EXIT_FAILURE);
    }
    // Zero out memory for the client information
    memset( & client, 0, sizeof(client));

    socklen_t client_len = sizeof(client);
    FD_ZERO( & set);
    FD_SET(server_fd, & set);

    select(server_fd + 1, & set, NULL, NULL, & timeout);

    // server times out after allowing 30 seconds for clients to join.
    // If no clients join function returns 0. Otherwise returns no_clients
    nready = FD_ISSET(server_fd, & set);
    printf("nready is: %d\n", nready);

    if (nready == 0) {
        return num_conn; // returns number of connections if a time out occurs. 
    }

    // Accept the connection from the client
    client_fd[num_conn] = accept(server_fd, (struct sockaddr * ) & client, & client_len);
    if (client_fd < 0) {
        fprintf(stderr, "Could not establish new connection\n");
        // SEND REJECT??
        exit(EXIT_FAILURE);
    }

    // Assign value to number of clients here and let it set after a time out
    // more work to  be done here
    printf("Accepted connection from client %d\n", num_conn);
    num_conn++;
}

【问题讨论】:

  • 不清楚您使用的是哪个操作系统,但来自man select“在 Linux 上,select() 修改超时以反映未睡眠的时间量;大多数其他实现不要这样做。(POSIX.1 允许任何一种行为。)"。看起来您依赖于未普遍实施的特定非标准行为。
  • 我正在使用 mac,我认为在这个操作系统上 FD_ISSET 用于检查客户端是否已连接(我很确定在 Linux 上不需要)。所以你可以像对待 linux 上 select 函数的返回值一样对待这个函数的返回值。
  • 如果您需要为每个套接字分别设置超时,您需要为它们设置某种优先级队列并为select选择最低超时

标签: c select tcp server timeout


【解决方案1】:
select(server_fd + 1, & set, NULL, NULL, & timeout);

您的代码依赖于选择修改您在循环外设置的timeout,以便timeout 反映剩余时间。但是您不能依赖这种行为,因为它只针对某些平台,例如 Linux。

特别是在您的平台 MacOS 上,man page of select 明确指出超时不会以您所依赖的方式更改:

...要进行轮询,超时参数应该是 非零,指向一个零值时间结构。 超时不 由 select() 更改,并且可以在后续调用中重用,但是它是 在每次调用 select() 之前重新初始化它的好风格。

这意味着您必须自己计算在select 上花费的时间,并在再次调用select 时相应地调整timeout

【讨论】:

    猜你喜欢
    • 2015-02-14
    • 2013-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 2022-01-17
    相关资源
    最近更新 更多