Кастинг между sockaddr и sockaddr_in6

87
9

Я читал Beej Guide to Network Programming и в одном из своих примеров он наводил указатель на struct sockaddr на указатель struct sockaddr_in6, как показано ниже.


    void *addr;
char *ipver;

// get the pointer to the address itself,
// different fields in IPv4 and IPv6:
if (p->ai_family == AF_INET) { // IPv4
struct sockaddr_in *ipv4 = (struct sockaddr_in *)p->ai_addr;
addr = &(ipv4->sin_addr);
ipver = "IPv4";
} else { // IPv6
struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
addr = &(ipv6->sin6_addr);
ipver = "IPv6";
}


Как это возможно, так как размеры структур различны?

спросил(а) 2021-01-19T15:32:34+03:00 2 месяца, 3 недели назад
1
Решение
96

ai_family и ai_addr являются полями структуры addrinfo, поэтому, предположительно, код, который вы цитируете, предварительно набрал getaddrinfo().


Результат getaddrinfo() - это связанный с NULL связанный список структур addrinfo, где поле addrinfo::ai_addr является указателем на выделенный блок памяти, который имеет достаточный размер для хранения адреса сокета сообщенного addrinfo::ai_family тип. Размер адреса указывается в поле addrinfo::ai_addrlen.


Для AF_INET поле addrinfo::ai_addr указывает на блок памяти, содержащий структуру sockaddr_in.

Для AF_INET6 поле addrinfo::ai_addr указывает на блок памяти, содержащий структуру sockaddr_in6.


Вот почему работают роли типа.


Поле addrinfo::ai_addr объявляется как struct sockaddr*, поэтому оно может передаваться как-есть в параметр addr функций bind() и connect() без литья типов. Поле addrinfo::ai_addrlen может быть передано как есть в их параметр addrlen.

ответил(а) 2021-01-19T15:32:34+03:00 2 месяца, 3 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема