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);
    }

и это из журнала:

Mar 6 10: 42: 04 tcpclient: fcntl ret=0, ret & O_NONBLOCK = 0

Mar 6 10: 42: 04 tcpclient: после выбора fcntl ret=0, ret & O_NONBLOCK = 0

Mar 6 10: 42: 14 tcpclient: аутентификация: ошибка при подключении -> операция выполняется

похоже, что это блокирующий сокет, но возвращает ошибка, типичная для неблокирующего? В Linux-2.6.18-308.el5. Есть идеи?

2 ответов


если timeout не 0 вызов connect() тайм-аут и возвращается. Это происходит независимо от того, было ли установлено соединение или нет.

С момента истечения тайм-аута connect() ведет себя так, как будто вызывается неблокирующий сокет.

ссылаясь на этот случай (дословно от man connect и игнорировать "тут" ниже):

EINPROGRESS

сокет не блокируется, и соединение не может быть закончено немедленно. Можно выбрать(2) или опрос (2) для завершения, выбрав сокет для записи. После того, как select (2) указывает на возможность записи, используйте getsockopt (2) чтобы прочитать параметр SO_ERROR на уровне SOL_SOCKET, чтобы определить, успешно ли connect() завершен (SO_ERROR равен нулю) или неудачно (SO_ERROR-один из обычных кодов ошибок, перечисленных здесь, объясните‐ ing причина неудачи).


Btw: Может кто-то подтверждает, что это стандартное поведение, и для этого явно где-то упоминал?

man 7 socket состояния (Курсив мой):

SO_RCVTIMEO и SO_SNDTIMEO

укажите время ожидания приема или отправки до сообщения об ошибке. [...] если данные не были переданы и тайм-аут был достигнут, то -1 возвращается с errno, установленным в EAGAIN или EWOULDBLOCK как если бы сокет был указан быть неблокирующим. [...] Тайм-ауты действуют только для системных вызовов, выполняющих ввод/вывод сокета (например, read (2), recvmsg (2), send (2), sendmsg(2)); тайм-ауты не влияют на select(2), poll(2), epoll_wait (2) и т. д.

ни слова о connect()поэтому я не уверен, что мой ответ держится.


попробуйте с ' if ((connect (...))