Когда getaddrinfo возвращает более одной структуры sockaddr в списке? - PullRequest
1 голос
/ 02 мая 2019

Я работаю с некоторым кодом, который нашел, и пытаюсь понять логику for loop в этом.

Кажется, что цикл for не используется, и он всегда будет разрываться.Так что я не понимаю, какая информация возвращается из getaddrinfo (), что может привести к повторному циклу и проверке чего-либо?

Вопрос: В основном, что это за цикл пытается выполнить?Мне кажется, это просто проверка того, что список не равен NULL, потому что цикл не выполняется, никогда.

tcp_ctx* tcp_new_ctx(INT family, CHAR *host, CHAR *port) {
    struct addrinfo *list = NULL;
    struct addrinfo *e = NULL;
    struct addrinfo hints;
    tcp_ctx         *c = NULL;
    WSADATA         wsa;
    INT             on = 1;

    WSAStartup(MAKEWORD(2, 0), &wsa);

    ZeroMemory(&hints, sizeof(hints));

    hints.ai_family = family;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

    // try to resolve network address for host
    //list contains linked list of addrinfo structs containing information on the host
    if (getaddrinfo(host, port, &hints, &list) != 0) {
        return NULL;
    }
    c = tcp_alloc(sizeof(tcp_ctx));

    // Traverse linked list from getaddr info
    for (e = list; e != NULL; e = e->ai_next) {
        if (family == AF_INET) {
            memcpy(&c->v4, e->ai_addr, e->ai_addrlen);
            c->ai_addr = (SOCKADDR*)&c->v4;
        } else if (family == AF_INET6) {
            memcpy(&c->v6, e->ai_addr, e->ai_addrlen);
            c->ai_addr = (SOCKADDR*)&c->v6;
        } else {
            return NULL;
        }
        c->ai_addrlen = e->ai_addrlen;
        // create socket and event for signalling
        c->s = socket(family, SOCK_STREAM, IPPROTO_TCP);
        if (c->s != SOCKET_ERROR) {
            // ensure we can reuse same port later
            setsockopt(c->s, SOL_SOCKET, SO_REUSEADDR, (CHAR*)&on, sizeof(on));
        }
        break;
    }
    freeaddrinfo(list);
    return c;
}

1 Ответ

3 голосов
/ 02 мая 2019

Что будет в списке?

Следующая цитата взята из справочной страницы getaddrinfo glibc , но AFAIK она в равной степени относится к версии для Windows:

Существует несколько причин, по которым в связанном списке может быть несколько структура addrinfo, в том числе: сетевой хост является многосетевым, доступным по нескольким протоколам (например, как AF_INET, так и AF_INET6); или же один и тот же сервис доступен из нескольких типов сокетов (один Например, адрес SOCK_STREAM и другой адрес SOCK_DGRAM).

Итак, в основном хост может иметь несколько способов связаться с ним, и getaddrinfo перечисляет все (известные) способы. Обратите внимание, что на этой же странице руководства также указано:

Обычно приложение должно пытаться использовать адреса в порядке в котором они возвращаются. Функция сортировки, используемая в getaddrinfo (), определена в RFC 3484;

Конечно, и здесь мы не знаем, относится ли это также к реализации (ам) Windows, но если это указано в RFC , то это может иметь место.

Что это за цикл пытается сделать?

В таком виде вы можете удалить петлю. Я думаю, что может быть причина сохранить (= исправить) это, хотя: Рассмотрим случай, когда первая возвращенная запись не имеет family ни AF_INET, ни AF_INET6. Код в ваших вопросах просто не работает (return NULL;), но в списке может быть более поздняя запись, которая может иметь это семейство.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...