【问题标题】:Knowing which file-descriptors are ready after select() call in C在 C 中调用 select() 后知道哪些文件描述符已准备就绪
【发布时间】:2014-03-30 01:32:09
【问题描述】:

我是套接字编程的新手,我被介绍给select() 系统调用。我的问题是,假设我正在用 C 语言编写服务器(我正在尝试这样做),并且我想在我的实现中使用 select() 调用进行练习。我正在尝试编写一个从客户端接收信息的服务器,所以我的方法是使用select(),然后使用read(),然后输出信息。

根据我读过的文档select() 返回输入集中准备好用于 i/o 的文件描述符的 number 个。我的问题是,如何知道原始集合中的 哪些 文件描述符是为 i/o 做好准备的?我似乎无法在我过去一段时间的搜索或示例中找到它。

假设我的代码如下所示:

int main() {
/* Create socket/server variables */
    int select_value;
    int this_socket;
    int maxfd;
    struct sockadder_in address; 
    fd_set allset;

    /* Bind the socket to a port */
    main_socket = socket(AF_INET, SOCK_STREAM, 0);
    if (main_socket < 0) {
        perror("socket()");
        exit(1);
    }

    Connect(main_socket, (struct sockaddr *)&address, sizeof(address));

    /* Add the socket to the list of fds to be monitored */
    FD_ZERO(&allset);
    FD_SET(main_socket, &allset);

    fd_set read_ready = allset;
    fd_set write_ready = allset;

    while (1) {
        /* Listen for a connection */
        /* Accept a connection */
        select_value = Select(maxfd+1, &read_ready, &write_ready, NULL, NULL);
        if (select_value == -1) {
            perror("select()");
            exit(1);
        }
        else if(select_value > 0) {
            /* How to access i/o ready file descriptors
            now that we know there are some available? */
        }
    }
} 

【问题讨论】:

  • 考虑使用poll(2) 而不是旧的select。谷歌“C10K 问题”
  • 我一定会在未来的实践项目中研究它,谢谢你的建议!
  • RTFM,尤其是 selectselect_tut 的联机帮助页。

标签: c sockets select-function


【解决方案1】:

可以使用FD_ISSET 宏来做到这一点,它是&lt;sys/select.h&gt; 的一部分。

当您的select 解除阻塞并且文件描述符准备就绪时,您可以使用FD_ISSET 宏在一个简单的循环中测试所有文件描述符。这可以翻译成以下示例:

for (i = 0; i < FD_SETSIZE; ++i) {
    if (FD_ISSET (i, &read_fd_set)) {
        if (i == bound_socket) {
            // A new client is waiting to be accepted
            new = accept(sock, (struct sockaddr *) &clientname, &size);
            // ...
            FD_SET (new, &active_fd_set);
        }
        else {
          // There is something to be read on the file descriptor.
          data = read_from_client_on(i);
        }
    }
}

当然,这只是示例,显然缺少任何错误处理,您应该在应用程序中处理。

【讨论】:

  • 非常感谢,这是一个简单的解释。我忘了select()是作为位掩码实现的,所以直到看到你的解释和循环,我才明白FD_SET的用法。
猜你喜欢
  • 2016-05-10
  • 2019-10-16
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 2019-10-09
  • 1970-01-01
  • 2015-07-01
  • 2014-07-02
相关资源
最近更新 更多