2015-02-07 4 views
6

Я пишу программу, которая будет подключаться к различным веб-сайтам и запрашивать и загружать веб-страницы. Я делаю это в значительной степени, чтобы научиться и правильно понимать веб-программирование. Я хотел бы знать, если указатель на связанный список типа , возвращаемый getaddrinfo, упорядочен в любом конкретном порядке, и если так выбран ip-адрес для подключения к материю каким-либо образом.Какую структуру addrinfo следует использовать в connect()?

Например, если я запустил getaddrinfo("google.com", "http", &hints, &res), res будет иметь до семи интернет-адресов. Разве это имеет какое-то значение, если я подключаюсь к первому или последнему? Обратите внимание, что я изучил страницы руководства для этой функции и, насколько мне известно, на мой вопрос не ответил.

+0

Я бы предположил, что заказ такой же, как и запись DNS для домена, который вы искали. Не забудьте вызвать freeaddrinfo(), когда закончите с результатом. – Yetti99

+0

Спасибо, я верю, что и частично ответил на другой вопрос, который я собирался исследовать, когда продвигаюсь дальше. (если вам интересно, это как getaddrinfo получить эту информацию?, я планирую прочитать некоторый источник для libc после того, как я закончу его изучение). – FutureSci

+1

getaddrinfo выполняет DNS-запрос. Вы можете прочитать об этом в Википедии. Если у вас есть командная строка Linux, вы можете запускать команды dig или nslookup - они могут использовать getaddrinfo, но, возможно, делают это напрямую, так как они предоставляют всю информацию. Вот сайт, который дает вам доступ - http://network-tools.com/nslook/ – Yetti99

ответ

3

Поскольку у вас есть несколько addrinfo структур, организованных в связанном списке, вы должны итерации над ней и попытаться connect, пока соединение не будет успешным. То есть:

struct addrinfo *ptr = res; 

while (res != NULL) { 
    int rc = connect(socket_fd, (sockaddr *) ptr->ai_addr, ptr->addr_len); 
    if (rc == 0) 
     break; // we managed to connect successfully 
    // handle error 

Это может быть необходимо, потому что DNS поиск может возвращать несколько записей, таким образом, необходимость иметь связанный список для того, чтобы позволить вам получить доступ к ним. Если connect преуспевает, все готово; если он терпит неудачу, вы должны продолжать пытаться для каждого доступного IP-адреса возврату, поэтому продвигайте указатель на следующий элемент. Более того, считайте, что connect может выйти из строя по нескольким причинам, поэтому вам необходимо проверить errno на наличие ошибок, которые могут позволить дальнейшие попытки. Как отметил @R .., вам также необходимо передать connect новый сокет, поскольку семейство адресов может измениться, высвободив предыдущий; getaddrinfo поможет вам, поскольку эта информация предоставляется в узле addrinfo (ai_family).

Однако, как правило, не нужен: первый результат обычно будет работать. Лично, если я могу, я никогда не сталкивался с необходимостью перебирать связанный список, но все равно хорошо знать, если вам это может понадобиться.

getaddrinfo(3)

Есть несколько причин, почему связанный список может иметь более чем одну структуру addrinfo, в том числе: сети хоста Multihomed, доступен на нескольких протоколов (например, как AF_INET и AF_INET6); или одна и та же услуга доступна из нескольких типов сокетов (например, один адрес SOCK_STREAM и другой адрес SOCK_DGRAM). Обычно приложение должно пытаться использовать адреса в том порядке, в котором они возвращаются. Функция сортировки, используемая в getaddrinfo(), определена в RFC 3484; порядок может быть изменен для конкретной системы, отредактировав /etc/gai.conf (доступный с glibc 2.5).

+1

Просто выполнение 'connect' в цикле не будет работать, если вы не заставляете семейство адресов (IPv4 или IPv6) или не использовали' AI_V4MAPPED', чтобы вы могли обрабатывать одинаковые. В противном случае вам нужно «закрыть» и снова открыть «сокет» с правильным семейством адресов для каждого вашего адреса. –

+0

@R .. Вы правы. Добавление к ответу. – edmz

Смежные вопросы