2014-07-18 117 views
1

我只是想了解getaddrinfo()行为。sockaddr和IPv6地址

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

生成的IP(v4/v6)地址保存在(每个)struct 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到struct sockaddr_storage的

(struct sockaddr_storage *)(res->ai_addr) 

并且可能在GCC的警告结束:

警告:投增加目标类型的对齐要求

将sppaddr转换为sockaddr_storage的正确方法是什么?几个答案后

更新:

问题是在海湾合作委员会警告:

> 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_familyAF_INET,这真是一个指针sockaddr_in结构。
  • 如果ai_familyAF_INET6,它是指向结构的指针。

由于的sockaddr_in,和sockaddr_storagehttp://www.beej.us/guide/bgnet/output/html/multipage/sockaddr_inman.html)的结构中,则可以将指针如上所述投射到实际结构取决于ai_family

+0

'AF_INET'使用'sockaddr_in',而不是'sockaddr'。只是出于历史原因,'sockaddr'和'sockaddr_in'具有相同的字节大小。 –

0

您应该使用struct 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]; 
};