【问题标题】:C : non blocking sockets with timeout : how to avoid busy waiting?C:具有超时的非阻塞套接字:如何避免忙等待?
【发布时间】:2015-03-03 17:53:47
【问题描述】:

以下代码允许服务器等待客户端连接到(已经绑定的)套接字。 它在客户端连接到套接字时终止,或者在“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;                                                                                                                                                                                                                                             
}                    

根据对另一个帖子(C : non blocking sockets with timeout : how to check if connection request was made?)的回答和cmets,这不是要走的路,因为它涉及忙碌的等待。

例如评论说:

“使用阻塞 IO 处理关机的标准方法是使用 信号处理程序设置关闭标志,然后在何时检查标志 听返回 -1 并将 errno 设置为 EINTR"

我很不清楚上面的代码如何适应“使用信号处理程序”......

【问题讨论】:

  • 你的程序是多线程的吗?或者你提到的代码的其他部分是一个单独的程序,它与服务器共享*server_run内存?

标签: c sockets signals server nonblocking


【解决方案1】:

您想在套接字上select(),并且只有在准备好读取时才执行accept。 select() 有一个超时,所以你可以永远等待,或者在每个循环中等待一两秒更好,因为如果 FD 准备好,select 将立即退出(这里的“准备阅读”意味着“准备好接受')。

【讨论】:

  • 除了select() 的即时响应之外,您的超时建议相当于忙等待,与Vince 的usleep() 版本非常相似。
  • select() 怎么能有 1 秒超时忙等待?我怀疑你的超时有点错误。
  • 忙着等待:a technique in which a process repeatedly checks to see if a condition is true。超时时间的长短只是数量上的区别; select() 版本的定性特征与 usleep() 相同 - 每次超时后循环都很忙 - 并且控制对server_run 的最大响应时间的超时可以选择相等。
  • 确实如此。而且(根据该定义)它在select() 中并不忙于等待,这大约是 99.999% 的时间。
  • 如果超时选择相等,则它在usleep() 中等待的时间百分比相同。但重要的是整个循环,不仅仅是select() 或usleep(),因此它相当于忙于等待。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-12
  • 1970-01-01
  • 2015-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多