2014-07-18 159 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]; 
};