如何在套接字上正确使用 select()?

Ben*_*ist 5 c sockets select

我正在尝试调用select套接字,但我无法理解我做错了什么。

setup_server_socket调用bindlisten设置套接字为非阻塞模式。

以下代码select似乎阻塞了调用,而不是前进到FD_ISSET. 我尝试连接客户端,它似乎成功但select从未返回任何内容。

这样做的正确方法是什么?

...
int listenfd = setup_server_socket( serverPort );

if( -1 == listenfd )
    return 1;

fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;


// loop forever
while( 1 )
{
    if (select(fdmax+1, &read_fds, NULL,NULL,NULL) == -1){
        perror("select");
        exit(4);
    }

    for (int i = 0; i<= fdmax; i++){
        printf("Testing: %d, %d\n", i, FD_ISSET(i,&read_fds));

    }return 0;
...
Run Code Online (Sandbox Code Playgroud)

Bas*_*tch 8

多次阅读syscalls(2) , select(2) , select_tut(2) , poll(2) , errno(3)(顺便说一句,你应该更喜欢poll(2)而不是过时的select,它不处理大于__FD_SETSIZE,即我的 Linux/Debian/x86-64 系统上的 1024)。

然后:

fd_set read_fds;
FD_ZERO(&read_fds);
int fdmax = listenfd;
FD_SET(listenfd, &read_fds);
Run Code Online (Sandbox Code Playgroud)

应该去里面while(1) 循环中,调用之前select。顺便说一句,我建议使用poll而不是select

另请阅读有关C10k 问题的信息

不要忘记它select正在改变它给定的fd_set-s(并且通常希望它们是非空的)......

也许使用strace(1)gdb(1)。如果您使用GCC编译,请调用它gcc -Wall -Wextra -g以获取更多警告和调试信息。如果您使用Clang编译 C 代码,请考虑使用Clang 静态分析器

另请阅读Advanced Linux Programming(这是一本免费的书,您也可以在纸上阅读,或从其他几个地方下载,例如这个等等...)