You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android JNI中用C代码检测Node.js服务器是否在线的问题排查

Android JNI C代码检测Node.js服务器在线状态失败的问题排查与修复

核心错误分析

  • inet_pton使用错误:你把inet_pton的返回值直接赋值给server_addr.sin_addr.s_addr,但inet_pton的返回值是状态码(成功返回1、无效地址返回0、错误返回-1),并非转换后的二进制IP地址。正确逻辑是让函数把转换结果写入ip_bin,再将ip_bin.s_addr赋值给目标字段。
  • 套接字重复使用错误:第一次connect失败后调用close(sock)关闭了套接字,但后续循环未重新创建新套接字,已关闭的套接字无法再次用于连接操作。
  • 缺少错误排查信息:未打印connect失败的错误码,无法定位具体失败原因(如端口不匹配、权限限制、超时等)。

修正后的C代码实现

#include <errno.h>
#include <string.h>

const char *myIpAddress = "192.168.0.13";
#define PORT_NO 4000  // 必须与Node.js服务器监听端口一致
#define COUNT 10
#define PING_SLEEP_RATE 500000  // 每次重试间隔500ms

void check_server_online() {
    struct in_addr ip_bin;
    // 先验证IP地址转换是否成功
    if (inet_pton(AF_INET, myIpAddress, &ip_bin) != 1) {
        __android_log_print(ANDROID_LOG_ERROR, "MyApp", "Invalid IP address: %s", myIpAddress);
        my_call_back_func("0");
        return;
    }

    struct sockaddr_in server_addr;
    memset(&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT_NO);
    server_addr.sin_addr = ip_bin;  // 直接赋值转换后的IP结构

    __android_log_print(ANDROID_LOG_WARN, "MyApp", "Binary representation of %s: %x\n", myIpAddress, ntohl(ip_bin.s_addr));

    for (int i = 0; i < COUNT; i++) {
        __android_log_print(ANDROID_LOG_WARN, "MyApp", "\n>>> %d CONNECTION ATTEMPT <<<", i);
        
        // 每次重试都创建新的套接字
        int sock = socket(AF_INET, SOCK_STREAM, 0);
        if (sock < 0) {
            __android_log_print(ANDROID_LOG_ERROR, "MyApp", "Socket creation failed: errno=%d", errno);
            usleep(PING_SLEEP_RATE);
            continue;
        }

        // 可选:设置2秒连接超时,避免长时间阻塞
        struct timeval timeout;
        timeout.tv_sec = 2;
        timeout.tv_usec = 0;
        setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout));

        int conn_result = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
        if (conn_result >= 0) {
            close(sock);
            __android_log_print(ANDROID_LOG_WARN, "MyApp", "\n>>> IP connection successful !!! <<<");
            my_call_back_func("1");
            return;
        } else {
            __android_log_print(ANDROID_LOG_ERROR, "MyApp", "Connect failed (attempt %d): errno=%d, %s", i, errno, strerror(errno));
            close(sock);
        }

        usleep(PING_SLEEP_RATE);
    }

    // 所有重试均失败
    my_call_back_func("0");
}

Node.js服务器侧注意事项

  • 确保MY_PORT为4000(与C代码PORT_NO一致),可通过启动日志确认监听端口。
  • 若需要允许局域网内所有设备访问,可将MY_HOST改为"0.0.0.0",避免仅绑定特定IP导致无法连接。
  • 确认Android设备与服务器处于同一局域网,且无防火墙、路由器规则拦截4000端口的TCP连接。

内容的提问来源于stack exchange,提问作者Program-Me-Rev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 12:51:17