sockaddr和IPv6地址

时间:2014-07-18 05:13:14

标签: c sockets unix

我只是想了解getaddrinfo()的行为。

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中,该ai_addr的类型为sockaddr,其大小为< IPv6地址。

我的问题是,我正在将ai_addr类型转换为sockaddr_storage

(struct sockaddr_storage *)(res->ai_addr)

结束gcc警告:

  

警告:强制转换会增加目标类型所需的对齐

将sockaddr强制转换为sockaddr_storage的正确方法是什么?

几个答案后更新:

关于gcc警告的问题:

> warning: cast increases required alignment of target type

并通过以下方式解决:

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

2 个答案:

答案 0 :(得分:3)

ai_addr只是一个指针。取决于ai_familyai_addr背后的实际结构不同:

  • 如果ai_familyAF_INET,它实际上是指向sockaddr_in结构的指针。
  • 如果ai_familyAF_INET6,则它是指向sockaddr_in6结构的指针。

由于sockaddr_insockaddr_in6sockaddr_storagehttp://www.beej.us/guide/bgnet/output/html/multipage/sockaddr_inman.html)的结构,您可以根据ai_family将指针强制转换为实际结构如上所述。

答案 1 :(得分: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];
};