我正在编写一个连接到多个客户端的服务器。目前,我在 SOCK_STREAM 套接字上使用 accept 来连接新客户端。我希望能够接受来自将数据报发送到服务器的 SOCK_DGRAM 套接字的客户端的查询。由于接受只是挂起,直到客户端发送连接到该套接字的请求,我需要一种方法来监视两个套接字,直到一个接收到来自客户端的请求,然后才能处理该请求并返回监视套接字。我不需要立即处理请求(即,如果客户端在另一个客户端请求连接后发送查询,则查询客户端将不得不等待服务器完成连接客户端的请求,反之亦然)。我知道套接字可以提醒服务器有多少套接字准备读/写,但它如何告诉服务器哪个套接字准备好了? IE。哪个套接字准备好读取,哪个准备好写入?这是我的尝试,我知道监听器在连接后总是需要写入,而 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");
}
}
最佳答案
不是在 accept()
上阻塞,而是使用 select()
来告诉您客户端何时挂起,这样您就可以调用 accept()
没有阻塞。然后就可以同时监控TCP和UDP套接字了。您拥有的代码已经在正确的轨道上完成该任务,但是您正在使用 writing fdset 来检测何时调用 accept()
而您应该使用读取 fdset,并且您不会在每次循环迭代时重置 fdset 或超时,因为 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 ...
}
}
关于C:使用Select监听两个socket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29358443/