Неблокирующее соединение с обратным адресом (127.0.0.1 или localhost) - PullRequest
1 голос
/ 07 июня 2011

Когда я выполняю неблокирующее соединение с адресом обратной связи из симулятора iOS (который, вероятно, использует тот же стек TCP, что и Mac и FreeBSD), я вижу, что соединение всегда успешно, даже когда серверный процесс не запущен.

Я обнаружил, что соединение успешно установлено с помощью select () с нулевым тайм-аутом.Таким образом, до тех пор, пока select () возвращает 0, я предполагаю, что соединение установлено, если оно возвращает -1, у меня возникает ошибка с ошибкой, а если возвращается 1, сокет готов к чтению (так как сервер, должно быть, ответил)и я начинаю читать после сообщения об успешном подключении.

Это хорошо работает для всех адресов, кроме обратной петли.В loopback select () всегда возвращает 1, даже если сервер не запущен.Итак, я начинаю читать, что не получается, и я справляюсь с этим.Но я должен был обнаружить это через select ()!

Ответы [ 2 ]

3 голосов
/ 07 июня 2011

Вы получаете ошибку до , прямо на connect(). Прежде чем перейти к select(), убедитесь, что errno - это EINPROGRESS, а не что-то еще. В * BSD соединения с портом без прослушивания при ошибке localhost (или может ошибка) немедленно.

Я только что провел очень простой тест, подобный этому (заголовки пропущены):

int
main(void)
{
    int fd;
    int r;
    struct sockaddr_in remote;
    struct hostent *he;

    he = gethostbyname("localhost");
    if (he == NULL)
            return -1;

    memcpy(&remote.sin_addr, he->h_addr, sizeof(remote.sin_addr));
    remote.sin_port = htons(9671);
    remote.sin_family = AF_INET;

    fd = socket(PF_INET, SOCK_STREAM, 0);
    fcntl(fd, F_SETFL, O_NONBLOCK);

    r = connect(fd, (struct sockaddr *)&remote, sizeof remote);
    if (r < 0) {
            perror("connect");
    }
    return 0;
}

Ничего не слушая порт 9671, я получил:

  • в Linux: connect: Operation now in progress
  • во FreeBSD: connect: Connection refused

Конечно, всегда - хорошая идея проверить коды ошибок всех системных вызовов (то, что в приведенном выше примере не ради простоты - это всего лишь иллюстрация, в конце концов).

0 голосов
/ 08 июня 2011

Проблема заключалась в том, что я полагался на select (), чтобы сообщить мне, было ли соединение успешным.Выберите только говорит вам, если что-то изменилось на этом FD.Я должен был на самом деле снова вызвать connect () для сокета и убедиться, что если он не работает, то errno имеет значение EINPROGRESS, ECONN или EALREADY.За исключением ECONN, все остальные значения означают, что мы должны повторить попытку;ECONN означает, что он уже подключен.Любое другое значение errno означает, что нам не удалось подключиться.

...