В чем разница между struct addrinfo и struct sockaddr

Из того, что я понимаю, struct addrinfo используется для подготовки структуры адреса сокета, а struct sockaddr содержит информацию о адресе сокета. Но что это значит? struct addrinfo содержит указатель на struct sockaddr. Зачем держать их отдельно? Почему мы не можем объединить все вещи в sockaddr в addr_info?

Я просто догадываюсь, но причина их разделения заключается в том, чтобы сэкономить место при передаче структур? Например, в вызове bind() все, что ему нужно, это номер порта и интернет-адрес. Таким образом, оба они сгруппированы в структуру sockaddr. Итак, мы можем просто передать эту небольшую структуру вместо более крупной структуры addrinfo?

struct addrinfo {
    int              ai_flags;     // AI_PASSIVE, AI_CANONNAME, etc.
    int              ai_family;    // AF_INET, AF_INET6, AF_UNSPEC
    int              ai_socktype;  // SOCK_STREAM, SOCK_DGRAM
    int              ai_protocol;  // use 0 for "any"
    size_t           ai_addrlen;   // size of ai_addr in bytes
    struct sockaddr *ai_addr;      // struct sockaddr_in or _in6
    char            *ai_canonname; // full canonical hostname

    struct addrinfo *ai_next;      // linked list, next node
};

struct sockaddr {
    unsigned short    sa_family;    // address family, AF_xxx
    char              sa_data[14];  // 14 bytes of protocol address
}; 

Ответы

Ответ 1

struct addrinfo возвращается getaddrinfo() и содержит при успехе связанный список такого struct для указанного имени хоста и/или службы.

Элемент ai_addr на самом деле не является struct sockaddr, потому что struct является просто общим, который содержит общие члены для всех остальных, и используется для определения того, какой тип структуры вы на самом деле имеете, В зависимости от того, что вы переходите на getaddrinfo() и что эта функция обнаружила, ai_addr может фактически быть указателем на struct sockaddr_in или struct sockaddr_in6 или что-то еще, в зависимости от того, что подходит для этой конкретной записи адреса. Это одна из веских причин, по которым они сохраняются "отдельно", потому что этот член может указывать на одну из нескольких типов struct s, которые он не мог бы сделать, если бы вы попытались скопировать все члены в struct addrinfo, потому что у разных struct есть разные члены.

Это, вероятно, самый простой способ получить эту информацию, если у вас есть имя хоста, но это не единственный способ. Для подключения IPv4 вы можете просто заполнить структуру struct sockaddr_in самостоятельно, если хотите, и у вас есть данные, чтобы сделать это, и не пропустите римарол вызова getaddrinfo(), который вам, возможно, придется ждать, если он необходимо выйти в Интернет, чтобы собрать информацию для вас. Вам не нужно использовать struct addrinfo вообще.