更新:
我的坏。我得到的错误是ECONNREFUSED而不是EINPROGRESS。在检查error
变量后,我发现它大于0,我打印了errno
而不是error
。
当然,errno
为EINPROGRESS
,因为自connect()
调用后其值未发生变化。
问题回答。谢谢大家。
我使用与史蒂文斯的UNIX网络编程非关键连接()示例相同的代码:
- 将套接字设置为非阻塞
- 启动非阻塞连接()
- 检查是否立即完成
- 使用超时调用select()并等待读取或写入就绪
- 当select()返回值大于0时,执行getsockopt(socket,SOL_SOCKET,SO_ERROR,& error,& len)。
醇>我得到的错误是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);
答案 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()已因某些原因返回。