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

Iva*_*res 10 c sockets linux 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);
    }
Run Code Online (Sandbox Code Playgroud)

这是来自日志:

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

03月06日10时42分04秒的TcpClient:后选择的fcntl RET = 0,RET&O_NONBLOCK = 0

3月6日10:42:14 tcpclient:authenticate:连接时出错 - >现在正在进行操作

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

alk*_*alk 5

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

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

引用这种情况(下面是从动词man connect并忽略“ 立即 ”):

进步

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


顺便说一句:有人可以确认这是标准行为,对此在某处有明确提及吗?

man 7 socket 状态(我的斜体字):

SO_RCVTIMEO和SO_SNDTIMEO

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

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

  • 当然 `close()` 会使套接字无效。然而,操作系统可能会在 address:port 上保持一段时间。要在操作系统发布之前恢复地址:端口,您可以指定套接字选项`SO_REUSEADDR`。 (2认同)