我没有看到这类问题。由于单线程服务器应用程序的好处,这很奇怪。但是,当服务器处于非阻塞状态时,我如何在代码中实现超时系统?
目前我正在使用此方法。
while(true)
{
FD_ZERO(&readfds);
FD_SET(server_socket, &readfds);
for (std::size_t i = 0; i < cur_sockets.size(); i++)
{
uint32_t sd = cur_sockets.at(i).socket;
if(sd > 0)
FD_SET(sd, &readfds);
if(sd > max_sd){
max_sd = sd;
}
}
int activity = select( max_sd + 1 , &readfds, NULL , NULL, NULL);
if(activity < 0)
{
continue;
}
if (FD_ISSET(server_socket, &readfds))
{
struct sockaddr_in cli_addr;
uint32_t newsockfd = (uint_fast32_t)accept((int)server_socket,
(struct sockaddr *) &cli_addr,
&clientlength);
if(newsockfd < 1) {
continue;
}
//Ensure we can even accept the client...
if (num_clients >= op_max_clients) {
close(newsockfd);
continue;
}
fcntl(newsockfd, F_SETFL, O_NONBLOCK);
/* DISABLE TIMEOUT EXCEPTION FROM SIGPIPE */
#ifdef __APPLE__
int set = 1;
setsockopt(newsockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *) &set, sizeof(int));
#elif __LINUX__
signal(SIGPIPE, SIG_IGN);
#endif
/* ONCE WE ACCEPTED THE CONNECTION ADD CLIENT TO */
num_clients++;
client_con newCon;
newCon.socket = newsockfd;
time_t ltime;
time(<ime);
newCon.last_message = (uint64_t) ltime;
cur_sockets.push_back(newCon);
}
handle_clients();
}
正如您所知,我们在成功连接时为客户端添加了一个unix时间戳。我想可能会添加另一个每1秒休眠一次的线程,并且只是检查是否有任何客户在最长时间内没有发送任何发送,但我担心我会因为以下问题而陷入瓶颈第二个线程在处理大量连接时不断锁定。
谢谢,
AJM。
答案 0 :(得分:2)
select的最后一个参数是select调用的超时,select的返回代码告诉你,是否由于套接字准备好或因超时而返回。
为了对所有套接字实现自己的超时处理,您可以为每个套接字设置时间戳,并在任何套接字操作上更新它。然后在调用select之前计算每个套接字的超时,并使用select值调用超时的最小值。这只是基本的想法,可以更高效地实现它,这样您就不需要在调用select之前重新计算所有超时。但我认为一个单独的线程矫枉过正。