简体   繁体   English

C:无阻塞的超时套接字:如何避免繁忙的等待?

[英]C : non blocking sockets with timeout : how to avoid busy waiting?

The following code allows for a server to wait for a client to connect to a (already binded) socket. 以下代码允许服务器等待客户端连接到(已绑定)套接字。 It terminates either when a client connects to the socket, or when "server_run" takes the value 0: this allows other part of the code to shutdown the server when suitable to do so. 当客户端连接到套接字或“ server_run”值为0时,它终止:这允许代码的其他部分在适当的时候关闭服务器。

static inline int wait_for_client_to_connect(int sockfd, int* server_run){                                                                                                                                                                                  
  int client_found = 0;                                                                                                                                                                                                                                        
  int clientfd = 0;                                                                                                                                                                                                                                            
  struct sockaddr_in client_addr;                                                                                                                                                                                                                              
  int addrlen=sizeof(client_addr);                                                                                                                                                                                                                             
  if ( listen(sockfd,1) != 0 ) return -1;                                                                                                                                                                                                                      
  while ( client_found==0 && *server_run==1 ) {                                                                                                                                                                                                                 
    clientfd = accept(sockfd, (struct sockaddr*)&client_addr, &addrlen);                                                                                                                                                                                       
    if ( clientfd < 0 ) {                                                                                                                                                                                                                                      
      clientfd = 0;                                                                                                                                                                                                                                            
      if (errno==EAGAIN || errno==EWOULDBLOCK) usleep(10); // nobody connected, wait for request                                                                                                                                                               
      else return -1; // something wrong, send error                                                                                                                                                                                                           
    } else { // client found, configuring socket and exit                                                                                                                                                                                                      
      client_found=1;                                                                                                                                                                                                                                          
      int nodelay_flag = 1;                                                                                                                                                                                                                                    
      setsockopt(clientfd, IPPROTO_TCP, TCP_NODELAY, (void*) &nodelay_flag, sizeof(int)); // disable nagle algorithm                                                                                                                                           
    }                                                                                                                                                                                                                                                          
  }                                                                                                                                                                                                                                                            
  return clientfd;                                                                                                                                                                                                                                             
}                    

According to answer and comments to another posts ( C : non blocking sockets with timeout : how to check if connection request was made? ), this is not the way to go because it involves busy waiting. 根据对另一篇文章的回答和评论( C:具有超时的非阻塞套接字:如何检查是否发出连接请求? ),这不是可行的方法,因为它涉及繁忙的等待。

Eg a comment says : 例如,评论说:

"The standard way to handle shutdown with blocking IO is to use a signal handler to set a shutdown flag and then check the flag when listen returns -1 with errno set to EINTR" “使用阻塞的IO处理关机的标准方法是使用信号处理程序设置关机标志,然后在errno设置为EINTR的侦听返回-1时检查该标志”

It is very unclear to me how the code above could be adapted to "use a signal handler" .... 对我来说还不清楚如何将上面的代码修改为“使用信号处理程序”...。

You want to select() on the socket, and only do an accept if it is ready for reading. 您想在套接字上select() ,并且只有在准备好读取时才执行accept select() has a timeout, so you can wait either forever, or perhaps better for a second or two in each loop, as select will exit immediately if an FD is ready (here 'ready to read' means 'ready to accept'). select()有一个超时,因此您可以永久等待,或者在每个循环中等待一到两秒钟,因为如果FD准备就绪, select将立即退出(此处“ ready to read”表示“ ready to accept”) 。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM