2014-07-18 5 views
1

Я просто пытаюсь понять поведение getaddrinfo().sockaddr и адрес IPv6

int getaddrinfo(const char *node, const char *service, 
       const struct addrinfo *hints, 
       struct addrinfo **res); 

Результирующий IP (v4/v6) адреса данных, сохраненных в (каждой) структуре addrinfo.

struct addrinfo { 
    int    ai_flags; 
    int    ai_family; 
    int    ai_socktype; 
    int    ai_protocol; 
    socklen_t  ai_addrlen; 
    struct sockaddr *ai_addr; 
    char   *ai_canonname; 
    struct addrinfo *ai_next; 
}; 


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

Если один из результата является адрес IPv6 (16 байт), как оно может быть сохранено в ai_addr, который имеет тип SOCKADDR, размер которого < адрес IPv6.

Моя проблема в том, что я типа литья ai_addr для sockaddr_storage

(struct sockaddr_storage *)(res->ai_addr) 

И в конечном итоге в предупреждении GCC:

предупреждение: литые увеличивается требуемое выравнивание целевого типа

Каков правильный способ приведения типа sockaddr в sockaddr_storage?

Update после нескольких ответов:

Вопрос был на предупреждение GCC:

> warning: cast increases required alignment of target type 

И она решается с:

(struct sockaddr_storage *)(void *)(res->ai_addr) 
+0

Надеюсь, вы прочли это все, что мне когда-либо нужно было знать http://beej.us/guide/bgnet/output/html/singlepage/bgnet.html#lowlevel – MarkAWard

ответ

3

ai_addr - всего лишь указатель. В зависимости от ai_family, фактическая структура за ai_addr отличается:

  • если ai_family является AF_INET, это действительно указатель на sockaddr_in структуры.
  • если ai_family is AF_INET6, это указатель на структуру .

Благодаря структуре sockaddr_in, и sockaddr_storage (http://www.beej.us/guide/bgnet/output/html/multipage/sockaddr_inman.html), можно привести указатель на фактическую структуру в зависимости от ai_family, как описано выше.

+0

'AF_INET' использует' sockaddr_in', не 'sockaddr'. Просто бывает, что 'sockaddr' и' sockaddr_in' имеют одинаковый размер байта по историческим причинам. –

0

Вы должны использовать sockaddr_storage как тип сокета, так как ему достаточно велика для IPv4 и IPv6 и может быть отлита в sockaddr

struct sockaddr_storage { 
    sa_family_t ss_family;  // address family 

    // all this is padding, implementation specific, ignore it: 
    char  __ss_pad1[_SS_PAD1SIZE]; 
    int64_t __ss_align; 
    char  __ss_pad2[_SS_PAD2SIZE]; 
}; 
Смежные вопросы