给 1998 年风格的 socket 代码补 DNS 兜底

网络改造 · 2026-11-08 · datanger.cn

全站域名化改造时撞上了一个意料之中的墙:这套引擎只认点分 IP。配置里把服务器地址从 120.53.236.19 换成 datanger.cn,客户端直接连不上——没有任何报错,就是静默失败。

根因:inet_addr 的 INADDR_NONE

两处连接点(登录网关与更新检测)都走同一条路径:

sockaddr_in addr;
addr.sin_addr.s_addr = inet_addr(host);   // 域名 → INADDR_NONE (0xFFFFFFFF)
// 0xFFFFFFFF 恰好等于 255.255.255.255,connect 直接失败

inet_addr 解析失败返回 INADDR_NONE,而老代码从不检查这个返回值——静默失败的经典来源。补法很直接,在 CPipeState_Connecting 里加一层兜底:

u_long ip = inet_addr(host);
if (ip == INADDR_NONE) {
    HOSTENT* he = gethostbyname(host);
    if (he && he->h_addr_list[0])
        ip = *(u_long*)he->h_addr_list[0];
    else
        return ConnectFailed();          // 明确失败,别静默
}

阻塞与线程边界

gethostbyname 是阻塞调用,风险在连接线程里的语义。这套引擎的连接状态机跑在独立线程里,卡几百毫秒可以接受;如果状态机在主循环里,就得换成异步解析或先解析后连接。改造前先确认线程模型,别盲抄。

改完的验收标准很朴素:netstat 里客户端只持有 datanger.cn 解析出的地址,ESTABLISHED 到 6000 端口,配置文件里再也找不到一个裸 IP。