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

时间:2012-06-22 06:28:39

标签: c sockets network-programming

我们的应用程序使用带有连接和选择操作的非阻塞套接字用法(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;
    }

    .   
    .   
    .
    .
    .}  

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

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


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

3 个答案:

答案 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()隐式地将你的地址绑定到套接字。