connect()在阻塞套接字上返回“正在进行中的操作”?

时间:2013-03-06 09:54:27

标签: c linux sockets timeout connect

我有一个阻塞套接字(至少它在以下代码中出现):

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock < 0) {
            ERROR("%s: error opening socket", __func__);
            return (RESP_ERROR);
    }

    t.tv_sec = timeout;
    t.tv_usec = 0;

    int rf = fcntl(sock, F_GETFD);
    ERROR("fcntl ret=%d, ret & O_NONBLOCK = %d", rf, rf & O_NONBLOCK);

    if ((setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&t, sizeof (t)) < 0)
        || (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&t, sizeof (t)))) {
            strerror_r(errno, err, 254);
            ERROR("%s: error on setsockopt -> %s", __func__, err);
            close(sock);
            return (RESP_ERROR);
    }

    rf = fcntl(sock, F_GETFD);
    ERROR("after select fcntl ret=%d, ret & O_NONBLOCK = %d", rf, rf & O_NONBLOCK);

    if (connect(sock, (struct sockaddr *)&dst, sizeof (dst)) != 0) {
            strerror_r(errno, err, 254);
            ERROR("%s: error on connect -> %s", __func__, err);
            close(sock);
            return (RESP_ERROR);
    }

这是来自日志:

  

3月6日10:42:04 tcpclient:fcntl ret = 0,ret&amp; O_NONBLOCK = 0

     

3月6日10:42:04 tcpclient:选择fcntl ret = 0后,ret&amp; O_NONBLOCK = 0

     

3月6日10:42:14 tcpclient:authenticate:连接时出错 - &gt;正在进行中的操作

看来这是一个阻塞套接字但是返回非阻塞的典型错误? Linux是2.6.18-308.el5。有什么想法吗?

2 个答案:

答案 0 :(得分:5)

如果timeout不是0,则connect()的呼叫会超时并返回。这种情况与连接是否建立无关。

从超时到期的那一刻起,connect()的行为就像在非阻塞套接字上调用一样。

参考此案例(从man connect逐字逐句忽略“立即”):

  

EINPROGRESS

     

套接字是非阻塞的,无法立即完成连接。通过选择用于写入的套接字,可以选择(2)或轮询(2)以完成。 select(2)表示可写性后,使用                 getsockopt(2)读取SOL_SOCKET级别的SO_ERROR选项以确定connect()是否成功完成(SO_ERROR为零)或失败(SO_ERROR是此处列出的常见错误代码之一,解释 -                 失败的原因)。


顺便说一下:有人可以确认这是标准行为,并且在某处提到了明确吗?

man 7 socket个州(我用斜体字):

  

SO_RCVTIMEO和SO_SNDTIMEO

     

指定接收或发送超时,直到报告错误为止。 [...]如果没有传输数据并且已达到超时,则返回-1,并将errno设置为EAGAIN或EWOULDBLOCK ,就像套接字是                 指定为非阻塞。 [...]超时仅对执行套接字I / O的系统调用有效(例如,read(2),recvmsg(2),send(2),                 SENDMSG(2));超时对select(2),poll(2),epoll_wait(2)等没有影响。

没有关于connect()的消息,所以我不确定我的答案是否成立。

答案 1 :(得分:1)

尝试'if((connect(...))&lt; 0)'。你可能根本没有收到任何错误。