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
相关产品推荐
相关产品推荐

