了解从 JDK8 到 JDK11 更改的 SocketAddress 的本机代码
Understanding native code of SocketAddress that changed from JDK8 to JDK11
来自 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
执行相同的操作?
So in JDK8 I could cast the SOCKADDR
to struck sockaddr *
[sic]
我猜你的意思是你可以按照你的描述将 指针转换为 SOCKADDR
。那是合理的,但是投射 SOCKADDR
本身是不合理的。
好消息:您仍然可以像以前一样做很多事情。 SOCKETADDRESS *
可以安全地转换为 struct sockaddr *
,并且可以通过现有函数比较通过这种方式获得的两个 struct sockaddr *
值。所提供的函数至少与 JDK 8 案例一样有效。 (这两种方式都完全有效,但这是另一回事)。
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
执行相同的操作?
So in JDK8 I could cast the
SOCKADDR
tostruck sockaddr *
[sic]
我猜你的意思是你可以按照你的描述将 指针转换为 SOCKADDR
。那是合理的,但是投射 SOCKADDR
本身是不合理的。
好消息:您仍然可以像以前一样做很多事情。 SOCKETADDRESS *
可以安全地转换为 struct sockaddr *
,并且可以通过现有函数比较通过这种方式获得的两个 struct sockaddr *
值。所提供的函数至少与 JDK 8 案例一样有效。 (这两种方式都完全有效,但这是另一回事)。