套接字选择失败并且正在进行操作 – 非阻塞模式

我们的应用程序使用非阻塞套接字使用连接和选择操作(c代码)。 pusedo代码如下

unsigned int ConnectToServer(struct sockaddr_in *pSelfAddr,struct sockaddr_in *pDestAddr) { int sktConnect = -1; sktConnect = socket(AF_INET,SOCK_STREAM,0); if(sktConnect == INVALID_SOCKET) return -1; fcntl(sktConnect,F_SETFL,fcntl(sktConnect,F_GETFL) | O_NONBLOCK); if(pSelfAddr != 0) { if(bind(sktConnect,(const struct sockaddr*)(void *)pSelfAddr,sizeof(*pSelfAddr)) != 0) { closesocket(sktConnect); return -1; } } errno = 0; int nRc = connect(sktConnect,(const struct sockaddr*)(void *)pDestAddr, sizeof(*pDestAddr)); if(nrC != -1) { return sktConnect; } if(errno != EINPROGRESS) { int savedError = errno; closesocket(sktConnect); return -1; } fd_set scanSet; FD_ZERO(&scanSet); FD_SET(sktConnect,&scanSet); struct timeval waitTime; waitTime.tv_sec = 2; waitTime.tv_usec = 0; int tmp; tmp = select(sktConnect +1, (fd_set*)0, &scanSet, (fd_set*)0,&waitTime); if(tmp == -1 || !FD_ISSET(sktConnect,&scanSet)) { int savedErrorNo = errno; writeLog("Connect %s failed after select, cause %d, error %s",inet_ntoa(pDestAddr->sin_addr),savedErrorNo,strerror(savedErrorNo)); closesocket(sktConnect); return -1; } . . . . .} 

问题陈述
在上面的代码中, select失败, error code 115是“正在进行操作”。 我没有看到有关errno 115 select失败的任何文档。

一个。 select何时在非阻塞套接字中失败并显示error code 115 ? 在什么情况下?
湾 我们是否看到任何提示此问题的系统日志。 只关心我们 – 我找不到任何描述这种问题的记录function。


PS:我们正在使用SUSE Linux 11企业版。

关于你的代码的一些想法:

我认为你的条件可以修改为只检查,如果select返回的值大于0,如果是这种情况,你可以检查socket的输出(对于SOL_SOCKET和SO_ERROR)选项( getsockopt(...,SOL_SOCKET, SO_ERROR,...,...) )以查看连接是否未通过。

我不太确定在连接成功的情况下,select是否总是将套接字返回为可写。 因此,在您的情况下,它可能( 仅可能 )是这样的情况:tmp变量不是-1并且它显示的errno是前一个connect调用的errno。

其他理由:

另一个很好的理由是,您要连接的目标地址要么无法访问,要么没有服务器在指定的地址+端口组合等待。 在这种情况下,您可以使用阻塞套接字尝试一次以查看是否连接。

错误的EINPROGRESS不是来自select(),它是从先前的connect()操作中遗留下来的。 如果select()返回-1 或未设置FD,则输入报告它的块。 所有这些意味着连接仍在进行中。 errno永远不会被清除,只有设置。

据我了解,您正在尝试与超时建立连接。

如果是这样,代码中就会出错。 在connect()调用之后但在select()之前,您应该使用fcntl()删除O_NONBLOCK选项。 否则select()将始终立即返回,因为使用套接字(具有O_NONBLOCK )的操作不会阻塞。

您读取的EINPROGRESS可能不是由select()生成,而是由之前的connect()调用生成的。

你也不应该在这里使用bind()调用,因为connect()隐式地将你的地址绑定到socket。