为什么单独实现,这是因为JAVA标准库提供的函数有性能问题,它会走DNS查询有网络IO,而且还是同步阻塞的,无论是客户端还是服务器,这都应该是不被允许的行为。
JNI实现:
bytes_to_address_string(byte[] address) 字节转IP地址字符串
string_to_address_bytes(string address) IP地址字符串转字节
// package: com.app.android.c
// public final class libxxx
// public native string bytes_to_address_string(byte[] address)
__LIBXXX__(jstring) Java_com_app_android_c_libxxx_bytes_1to_1address_1string(JNIEnv* env, jobject this_, jbyteArray address_) {__LIBXXX_MAIN__if (NULL == address_) {return env->NewStringUTF("0.0.0.0");}int length = env->GetArrayLength(address_);if (length < 4) {return env->NewStringUTF("0.0.0.0");}const char* address_bytes = (char*)env->GetByteArrayElements(address_, NULL);if (NULL == address_bytes) {return env->NewStringUTF("0.0.0.0");}char sz[INET6_ADDRSTRLEN];const char* r = inet_ntop(length >= 16 ? INET6_ADDRSTRLEN : AF_INET, (struct in_addr*)address_bytes, sz, sizeof(sz)); /* in6_addr */env->ReleaseByteArrayElements(address_, (jbyte*)address_bytes, 0);if (!r) {return env->NewStringUTF("0.0.0.0");}return env->NewStringUTF(sz); // inet_ntoa(*(struct in_addr*)address);
}// package: com.app.android.c
// public final class libxxx
// public native byte[] string_to_address_bytes(string address)
__LIBXXX__(jbyteArray) Java_com_app_android_c_libxxx_string_1to_1address_1bytes(JNIEnv* env, jobject this_, jstring address_) {__LIBXXX_MAIN__std::shared_ptr<app::string> address_managed = JNIENV_GetStringUTFChars(env, address_);uint8_t bytes[16];int af = 0;if (NULL == address_managed || address_managed->empty()) {*(uint32_t*)bytes = 0;af = AF_INET;}else {const char* address = NULL;if (NULL != address_managed) {address = address_managed->data();}struct sockaddr_in6 in6;int err = inet_pton(AF_INET6, address, &in6);if (err > 0) {af = AF_INET6;memcpy(bytes, &in6.sin6_addr, sizeof(bytes));}else {uint32_t addressV4 = inet_addr(address);if (addressV4 == htonl(INADDR_NONE)) {int b[4];if (sscanf(address, "%d.%d.%d.%d", &b[0], &b[1], &b[2], &b[3]) != 4) {return NULL;}}af = AF_INET;*(uint32_t*)bytes = addressV4;}}int result_count = af == AF_INET ? 4 : 16;jbyteArray result = env->NewByteArray(result_count);if (NULL == result) {return NULL;}jbyte* p = env->GetByteArrayElements(result, NULL);memcpy(p, bytes, result_count);env->ReleaseByteArrayElements(result, p, 0);return result;
}static std::shared_ptr<xxx::string> JNIENV_GetStringUTFChars(JNIEnv* env, const jstring& v) noexcept {std::shared_ptr<xxx::string> result;if (NULL != v) {char* s = (char*)env->GetStringUTFChars(v, NULL);if (NULL != s) {result = xxx::make_shared_object<xxx::string>(s);env->ReleaseStringUTFChars(v, s); }}return result;
}
Java:
// Convert a string to an IP address.@Nullablepublic static InetAddress string_to_address(String address) {try {byte[] V = libxxx.c.string_to_address_bytes(address);if (V == null) {return null;} else {return address_of(V);}} catch (Throwable ignored) {return null;}}// Convert a bytes to an IP address string.public static String bytes_to_address_string(byte[] address) {return libxxx.c.bytes_to_address_string(address);}