2

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

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 企业版。

4

3 回答 3

2

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

于 2012-06-22T23:55:55.397 回答
0

对您的代码的一些想法:

我认为您在选择下方的条件可以修改为仅检查是否选择返回大于 0 的值,如果是这种情况,您可以检查套接字的 getsockopt 输出(对于 SOL_SOCKET 和 SO_ERROR)选项(getsockopt(...,SOL_SOCKET, SO_ERROR,...,...))看看连接是否没有失败。

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

其他原因:

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

于 2012-06-22T06:42:12.940 回答
0

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

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

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

你也不应该bind()在这里使用 call 因为connect()隐式地将你的地址绑定到套接字。

于 2012-06-22T07:00:55.533 回答