C:使用Select监视两个插槽

CSj*_*kie 1 c sockets select server

我正在编写一个连接到多个客户端的服务器.目前,我在SOCK_STREAM套接字上使用accept来连接新客户端.我希望能够接受发送数据报到服务器的SOCK_DGRAM套接字的客户端的查询.由于accept只是挂起,直到客户端发送连接到该套接字的请求,我需要一种方法来监视两个套接字,直到一个接收到来自客户端的请求,然后能够处理该请求并返回监视套接字.我不需要立即处理请求(即,如果客户端在另一个客户端请求连接查询客户端之后发送查询,则必须等待服务器完成连接客户端的请求,反之亦然).我知道套接字可以提醒服务器有多少套接字可以读/写,但是它如何告诉服务器哪个套接字已准备就绪?即哪个套接字已准备好读取,哪个可以写入?这是我的尝试,我知道监听器在连接后总是需要写入,而udpSock总是需要读取.

 while(1){
        retval = select(max,&readSockSet, &writeSockSet, NULL, &timeout);
        if(retval){
            if(FD_ISSET(listener, &writeSockSet))
                printf("Client requesting to connect...\n");
            if(FD_ISSET(udpSock, &readSockSet))
                printf("Client query incoming...\n");
        }
    }
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

accept()您可以使用select()告诉您何时客户端处于挂起状态,而不是阻止,这样您就可以accept()不受阻塞地进行呼叫.然后,您可以同时监视TCP和UDP套接字.您所拥有的代码已经在正确的轨道上完成该任务,但是您正在使用写入 fdset来检测何时accept()应该使用读取 fdset 来调用,并且您不会在每次循环迭代时重置fdsets或timeout为select()修改它们.

试试这个:

fd_set readSockSet;
timeval timeout;
int smax = max(listener, udpSock);

while (1)
{
    FD_ZERO(&readSockSet);
    FD_SET(listener, &readSockSet);
    FD_SET(udpSock, &readSockSet);
    // add connected TCP clients, if needed...

    timeout.tv_sec = ...;
    timeout.tv_usec = ...;

    retval = select(smax+1, &readSockSet, NULL, NULL, &timeout);
    if (retval > 0)
    {
        if (FD_ISSET(listener, &readSockSet))
        {
            printf("TCP Client requesting to connect...\n");
            // call accept() and do something with the client socket ...
        }

        if (FD_ISSET(udpSock, &readSockSet))
        {
            printf("UDP Client query incoming...\n");
            // call recv()/read() to read the datagram ...
        }

        // check connected TCP clients, if needed...
    }
    else if (retval < 0)
    {
        // check errno/WSAGetLastError(), call perror(), etc ...
    }
}
Run Code Online (Sandbox Code Playgroud)