我们的应用程序使用带有连接和选择操作的非阻塞套接字用法(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
失败,即“正在进行操作”。我在select
上看不到errno 115
失败的任何文档。
一个。 select
何时在非阻塞套接字中失败并带有error code 115
?在什么情况下?
湾我们是否看到任何提示此问题的系统日志。只关心我们 - 我找不到任何描述此类问题的记录功能。
PS:我们正在使用SUSE Linux 11企业版。
答案 0 :(得分:1)
errno EINPROGRESS不是来自select(),它是从先前的connect()操作中遗留下来的。如果 select()返回-1 或未设置FD,则输入报告该块的块。所有这些意味着连接仍在进行中。 errno永远不会被清除,只能设置。
答案 1 :(得分:0)
关于您的代码的一些想法:
我认为你的条件可以修改为只检查,如果select返回的值大于0,如果是这种情况,你可以检查套接字的getsockopt输出(对于SOL_SOCKET和SO_ERROR)选项(getsockopt(...,SOL_SOCKET, SO_ERROR,...,...)
),以查看连接是否失败。
我不太确定在连接成功的情况下,select是否总是将套接字返回为可写。所以,在你的情况下,它可能是(只有),tmp变量不是-1,它显示的errno是前一次连接调用的errno。
其他原因:
另一个很好的理由是,您要连接的目标地址要么无法访问,要么没有服务器在指定的地址+端口组合等待。在这种情况下,您可以尝试使用阻塞套接字查看是否连接。
答案 2 :(得分:-1)
据我了解,您正在尝试与超时建立连接。
如果是这样,代码中就会出错。在connect()
来电之后select()
之前,您应该使用O_NONBLOCK
删除fcntl()
选项。否则select()
将始终立即返回,因为套接字(具有O_NONBLOCK
)的操作不会阻止。
您阅读的EINPROGRESS可能不是select()
生成的,而是先前connect()
次调用生成的。
你也不应该在这里使用bind()
调用因为connect()
隐式地将你的地址绑定到套接字。