@@ -1500,16 +1500,63 @@ static ResultList scan_ips(StringList *ips, Config *cfg, BaiduProxyPool *proxy_p
15001500 return rl ;
15011501}
15021502
1503+ static int http_probe (socket_t fd , int timeout_ms ) {
1504+ // 发送 HTTP GET 请求探测数据通路是否正常
1505+ const char * req = "GET / HTTP/1.0\r\nHost: cloudflaremirrors.com\r\nConnection: close\r\n\r\n" ;
1506+ size_t reqlen = strlen (req );
1507+ long deadline = now_ms () + timeout_ms ;
1508+ size_t sent = 0 ;
1509+ while (sent < reqlen && now_ms () < deadline ) {
1510+ fd_set wfds ;
1511+ FD_ZERO (& wfds );
1512+ FD_SET (fd , & wfds );
1513+ int left = (int )(deadline - now_ms ());
1514+ if (left <= 0 ) break ;
1515+ struct timeval tv = { left / 1000 , (left % 1000 ) * 1000 };
1516+ int rc = select (fd + 1 , NULL , & wfds , NULL , & tv );
1517+ if (rc <= 0 ) break ;
1518+ ssize_t n = send (fd , req + sent , reqlen - sent , 0 );
1519+ if (n <= 0 ) break ;
1520+ sent += (size_t )n ;
1521+ }
1522+ if (sent < reqlen ) return 0 ;
1523+ // 读取响应头,确认收到 HTTP 响应
1524+ char buf [256 ];
1525+ size_t used = 0 ;
1526+ while (used < sizeof (buf ) - 1 && now_ms () < deadline ) {
1527+ fd_set rfds ;
1528+ FD_ZERO (& rfds );
1529+ FD_SET (fd , & rfds );
1530+ int left = (int )(deadline - now_ms ());
1531+ if (left <= 0 ) break ;
1532+ struct timeval tv = { left / 1000 , (left % 1000 ) * 1000 };
1533+ int rc = select (fd + 1 , & rfds , NULL , NULL , & tv );
1534+ if (rc <= 0 ) break ;
1535+ ssize_t n = recv (fd , buf + used , sizeof (buf ) - used - 1 , 0 );
1536+ if (n <= 0 ) break ;
1537+ used += (size_t )n ;
1538+ buf [used ] = 0 ;
1539+ if (strstr (buf , "HTTP/" )) return 1 ; // 收到 HTTP 响应头表示数据通路正常
1540+ }
1541+ return 0 ;
1542+ }
1543+
15031544static int health_check_ip (const char * ip , BaiduProxyPool * proxy_pool ) {
15041545 int latency = 0 ;
1505- socket_t fd = dial_target_with_proxy (ip , g_cfg .port , 2000 , proxy_pool , & latency );
1546+ socket_t fd = dial_target_with_proxy (ip , g_cfg .port , g_cfg . delay_ms , proxy_pool , & latency );
15061547 if (cfnat_socket_invalid (fd )) {
1507- debug_msg ("健康检查失败: IP %s 暂不可用 " , ip );
1548+ debug_msg ("健康检查失败: IP %s TCP 不可达 " , ip );
15081549 return 0 ;
15091550 }
1551+ // TCP 握手成功后再做 HTTP 探测,确认数据通路正常
1552+ int ok = http_probe (fd , g_cfg .delay_ms );
15101553 close (fd );
1511- debug_msg ("健康检查成功: IP %s 延迟 %d ms" , ip , latency );
1512- return 1 ;
1554+ if (ok ) {
1555+ debug_msg ("健康检查成功: IP %s 延迟 %d ms" , ip , latency );
1556+ return 1 ;
1557+ }
1558+ debug_msg ("健康检查失败: IP %s TCP 可达但 HTTP 无响应" , ip );
1559+ return 0 ;
15131560}
15141561
15151562static int set_current_candidate (size_t idx ) {
@@ -1811,38 +1858,49 @@ static void *connection_thread(void *arg) {
18111858 return NULL ;
18121859}
18131860
1861+ static int carrier_probe_and_check (socket_t fd , int timeout_ms ) {
1862+ // TCP 握手成功后做 HTTP 探测,确认数据通路正常
1863+ int ok = http_probe (fd , timeout_ms );
1864+ close (fd );
1865+ return ok ;
1866+ }
1867+
18141868static int carrier_health_check_ip (CarrierRuntime * rt , const char * ip ) {
18151869 if (!rt || !ip || !* ip ) return 0 ;
18161870 // 混合模式:先试直连,不行再试百度代理
18171871 if (rt -> spec .use_baidu_proxy == 2 ) {
18181872 int latency = 0 ;
1819- socket_t fd = dial_target_with_proxy (ip , g_cfg .port , 2000 , NULL , & latency );
1873+ socket_t fd = dial_target_with_proxy (ip , g_cfg .port , g_cfg . delay_ms , NULL , & latency );
18201874 if (cfnat_socket_valid (fd )) {
1821- close (fd );
1822- debug_msg ("%s 健康检查成功(直连): IP %s 延迟 %d ms" , carrier_display_name (rt -> spec .mode ), ip , latency );
1823- return 1 ;
1824- }
1825- if (rt -> proxy_pool && rt -> proxy_pool -> len > 0 ) {
1826- fd = dial_target_with_proxy (ip , g_cfg .port , 2000 , rt -> proxy_pool , & latency );
1827- if (cfnat_socket_valid (fd )) {
1828- close (fd );
1829- debug_msg ("%s 健康检查成功(百度前置): IP %s 延迟 %d ms" , carrier_display_name (rt -> spec .mode ), ip , latency );
1875+ if (carrier_probe_and_check (fd , g_cfg .delay_ms )) {
1876+ debug_msg ("%s 健康检查成功(直连): IP %s 延迟 %d ms" , carrier_display_name (rt -> spec .mode ), ip , latency );
18301877 return 1 ;
18311878 }
1879+ } else if (rt -> proxy_pool && rt -> proxy_pool -> len > 0 ) {
1880+ fd = dial_target_with_proxy (ip , g_cfg .port , g_cfg .delay_ms , rt -> proxy_pool , & latency );
1881+ if (cfnat_socket_valid (fd )) {
1882+ if (carrier_probe_and_check (fd , g_cfg .delay_ms )) {
1883+ debug_msg ("%s 健康检查成功(百度前置): IP %s 延迟 %d ms" , carrier_display_name (rt -> spec .mode ), ip , latency );
1884+ return 1 ;
1885+ }
1886+ }
18321887 }
18331888 debug_msg ("%s 健康检查失败: IP %s 暂不可用" , carrier_display_name (rt -> spec .mode ), ip );
18341889 return 0 ;
18351890 }
18361891 // 普通模式
18371892 int latency = 0 ;
1838- socket_t fd = dial_target_with_proxy (ip , g_cfg .port , 2000 , rt -> proxy_pool , & latency );
1893+ socket_t fd = dial_target_with_proxy (ip , g_cfg .port , g_cfg . delay_ms , rt -> proxy_pool , & latency );
18391894 if (cfnat_socket_invalid (fd )) {
18401895 debug_msg ("%s 健康检查失败: IP %s 暂不可用" , carrier_display_name (rt -> spec .mode ), ip );
18411896 return 0 ;
18421897 }
1843- close (fd );
1844- debug_msg ("%s 健康检查成功: IP %s 延迟 %d ms" , carrier_display_name (rt -> spec .mode ), ip , latency );
1845- return 1 ;
1898+ if (carrier_probe_and_check (fd , g_cfg .delay_ms )) {
1899+ debug_msg ("%s 健康检查成功: IP %s 延迟 %d ms" , carrier_display_name (rt -> spec .mode ), ip , latency );
1900+ return 1 ;
1901+ }
1902+ debug_msg ("%s 健康检查失败: IP %s TCP 可达但 HTTP 无响应" , carrier_display_name (rt -> spec .mode ), ip );
1903+ return 0 ;
18461904}
18471905
18481906static int carrier_set_current_candidate (CarrierRuntime * rt , size_t idx ) {
0 commit comments