【问题标题】:Understanding native code of SocketAddress that changed from JDK8 to JDK11了解从 JDK8 到 JDK11 的 SocketAddress 的本机代码
【发布时间】:2020-03-26 01:33:49
【问题描述】:

来自 JDK8 的net_util_md.h 具有以下套接字地址代码:

#ifdef AF_INET6

#define SOCKADDR        union { \
                            struct sockaddr_in him4; \
                            struct sockaddr_in6 him6; \
                        }

#define SOCKADDR_LEN    (ipv6_available() ? sizeof(SOCKADDR) : \
                         sizeof(struct sockaddr_in))

#else

#define SOCKADDR        union { struct sockaddr_in him4; }
#define SOCKADDR_LEN    sizeof(SOCKADDR)

#endif

来自 JDK11 的net_util_md.h 现在具有以下套接字地址代码:

typedef union {
    struct sockaddr     sa;
    struct sockaddr_in  sa4;
    struct sockaddr_in6 sa6;
} SOCKETADDRESS;

所以在 JDK8 中,我可以将对 SOCKADDR 的引用转换为 struck sockaddr * 并与以下 C 代码进行比较:

int sockaddr_cmp(struct sockaddr *x, struct sockaddr *y)
{
#define CMP(a, b) if (a != b) return a < b ? -1 : 1

    CMP(x->sa_family, y->sa_family);

    if (x->sa_family == AF_UNIX) {
        struct sockaddr_un *xun = (void*)x, *yun = (void*)y;
        int r = strcmp(xun->sun_path, yun->sun_path);
        if (r != 0)
            return r;
    } else if (x->sa_family == AF_INET) {
        struct sockaddr_in *xin = (void*)x, *yin = (void*)y;
        CMP(ntohl(xin->sin_addr.s_addr), ntohl(yin->sin_addr.s_addr));
        CMP(ntohs(xin->sin_port), ntohs(yin->sin_port));
    } else if (x->sa_family == AF_INET6) {
        struct sockaddr_in6 *xin6 = (void*)x, *yin6 = (void*)y;
        int r = memcmp(xin6->sin6_addr.s6_addr, yin6->sin6_addr.s6_addr, sizeof(xin6->sin6_addr.s6_addr));
        if (r != 0) {
            return r;
         }
        CMP(ntohs(xin6->sin6_port), ntohs(yin6->sin6_port));
        CMP(xin6->sin6_flowinfo, yin6->sin6_flowinfo);
        CMP(xin6->sin6_scope_id, yin6->sin6_scope_id);
    } else {
        return -1;
    }

#undef CMP
    return 0;
}

如何使用来自 JDK11 的新 SOCKETADDRESS 做同样的事情?

【问题讨论】:

    标签: c sockets ip


    【解决方案1】:

    所以在 JDK8 中我可以将 SOCKADDR 转换为 struck sockaddr * [原文如此]

    我想你的意思是你可以像你描述的那样将指针指向SOCKADDR。这是合理的,但投射 SOCKADDR 本身就不行。

    好消息:您仍然可以像以前一样做很多事情。 SOCKETADDRESS * 可以安全地转换为 struct sockaddr *,并且可以通过现有函数比较以这种方式获得的两个 struct sockaddr * 值。所提供的功能至少与 JDK 8 案例一样有效。 (这两种方法都完全有效,但这是另一回事)。

    【讨论】:

    • 谢谢@John。是的,我的意思是我可以将 reference 投射到SOCKADDRstruct sockaddr *。我很困惑,因为新联合有 3 个字段而不是 2 个字段。它们如何等效以进行比较?
    • @CCCoder,一个联合的所有成员的存储都是重叠的,不管有多少成员。您的整个方法都取决于此。
    • 如您所见,我是 C 的新手,试图维护一些代码。我知道,那很危险。我不知道工会是重叠的。所以 Union 只是为相同的数据提供了类型的同义词,对吗?
    • 有些人确实是这样想的,@CCCoder,但从技术上讲它并不正确。这里有几个微妙之处,但最正确的思考方式是联合为不同类型的对象提供存储,一次一个。只有在某些情况下,并且在有限的范围内,它在技术上才允许通过与用于存储它的类型不同的成员访问当前存储在其中的对象。
    • 知道了!非常感谢!爱C,就是这么简单:P
    猜你喜欢
    • 2021-10-25
    • 2019-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-20
    • 2022-12-09
    • 2019-11-04
    相关资源
    最近更新 更多