getsockopt()在非阻塞connect()+ select()流中返回EINPROGRESS

时间:2009-07-08 12:31:32

标签: c++ c sockets unix

更新

我的坏。我得到的错误是ECONNREFUSED而不是EINPROGRESS。在检查error变量后,我发现它大于0,我打印了errno而不是error。 当然,errnoEINPROGRESS,因为自connect()调用后其值未发生变化。

问题回答。谢谢大家。

  

我使用与史蒂文斯的UNIX网络编程非关键连接()示例相同的代码:

     
      
  1. 将套接字设置为非阻塞
  2.   
  3. 启动非阻塞连接()
  4.   
  5. 检查是否立即完成
  6.   
  7. 使用超时调用select()并等待读取或写入就绪
  8.   
  9. 当select()返回值大于0时,执行getsockopt(socket,SOL_SOCKET,SO_ERROR,& error,& len)。
  10.         

    我得到的错误是EINPROGRESS。   代码在rhel5服务器上执行。

         

    为什么我收到此错误的任何想法?

代码段

 flags = fcntl(sockfd, F_GETFL, 0);
 fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

 if ((retVal = connect(sockfd, saptr, salen)) < 0)
     if (errno != EINPROGRESS)
  return (-1);

 if (retVal == 0)
 {
     // restore file status flags
     fcntl(sockfd, F_SETFL, flags);  
     return 0;
 }

 FD_ZERO(&rset);
 FD_SET(sockfd, &rset);
 wset = rset;
 tval.tv_sec = nsec;
 tval.tv_usec = 0;

 if ((retVal = select(sockfd + 1, &rset, &wset, NULL, &tval)) == 0) 
 {
     // timeout
     close(sockfd);          
     errno = ETIMEDOUT;
     return (-1);
 }

 if (retVal < 0) 
 {
     // select() failed
     return (-1);
 }

 if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) 
 {
     len = sizeof(error);
     error = 0;
     if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
  return (-1);     

     if (error > 0) //<<<<< error == EINPROGRESS >>>
     { 
  close(sockfd);
  errno = error;
  return (-1);
     }
 } 
 else
 {
     return (-1);
 }

 // restore file status flags
 fcntl(sockfd, F_SETFL, flags);  

3 个答案:

答案 0 :(得分:4)

哎呀......我放弃了。我尝试过但尝试过但找不到代码问题。 所以,我提供的只是一些建议和假设。

  • 使用FD_COPY将rset复制到wset。

  • 第一次连接失败时可以执行getsockopt吗? 我怀疑Select返回0并且由于上面的原因,你的writefd集被设置并且做一个getsockopt正在返回你之前连接的陈旧错误。 IMO,一个后续连接应返回EALREADY(尽管它可能与平台有关)

请执行以上操作(如果我错误地使用FD_COPY,请向我投票)并分享结果

答案 1 :(得分:2)

大于零的选择值不表示任何类型的错误......它是符合select语句标准的套接字数。如果发生故障,select将返回-1。

当使用SO_ERROR调用getsocktopt时,我不清楚是否有效;每次使用套接字时,你最好坚持检查错误(我认为你正在做的事情)。选择没有失败,你没事。

答案 2 :(得分:2)

EINPROGRESS表示非阻塞connect()仍在进行中。

所以我会问 - 你是否在select()返回后检查是否仍然在writefds fd_set中设置了connect()文件描述符?如果不是,则表示select()已因某些原因返回。