【问题标题】:sockaddr and IPv6 addresssockaddr 和 IPv6 地址
【发布时间】:2014-07-18 05:13:14
【问题描述】:

我只是想了解 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 类型转换为 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)

【问题讨论】:

标签: c sockets unix


【解决方案1】:

ai_addr 只是一个指针。根据ai_familyai_addr 背后的实际结构有所不同:

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

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

【讨论】:

  • AF_INET 使用 sockaddr_in,而不是 sockaddr。碰巧sockaddrsockaddr_in 由于历史原因具有相同的字节大小。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-09-23
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2010-12-21
    • 2011-08-31
    • 1970-01-01
    相关资源
    最近更新 更多