JNI实现一组字节数组转IP地址、IP地址转数组的函数

为什么单独实现,这是因为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.
    @Nullable
    public 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);
    }

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值