#!/usr/bin/env node // 连接诊断: TCP / WS 分段计时, 零依赖, Node >= 22 (内置 WebSocket) // 用法: node tools/diag-connection.mjs ws://192.168.1.5:3001 [次数] // 说明: WS 模式下服务端需对 {"type":"ping"} 回应任意消息(建议 {"type":"pong"}) import net from "node:net"; const url = process.argv[2]; const times = Number(process.argv[3] || 5); if (!url) { console.error("用法: node tools/diag-connection.mjs [次数]"); process.exit(1); } const u = new URL(url); const host = u.hostname; const port = Number(u.port || (u.protocol === "wss:" || u.protocol === "https:" ? 443 : 80)); const isWs = u.protocol === "ws:" || u.protocol === "wss:"; const tcpMs = [], openMs = [], rttMs = []; for (let i = 0; i < times; i++) { const t0 = performance.now(); try { await new Promise((res, rej) => { const s = net.connect({ host, port }); const to = setTimeout(() => { s.destroy(); rej(new Error("TCP timeout")); }, 3000); s.once("connect", () => { clearTimeout(to); tcpMs.push(performance.now() - t0); s.destroy(); res(); }); s.once("error", (e) => { clearTimeout(to); rej(e); }); }); } catch (err) { tcpMs.push(-1); console.warn("第" + (i+1) + "次 TCP 失败: " + err.message); } if (!isWs) continue; const t1 = performance.now(); try { const ws = new WebSocket(url); await new Promise((res, rej) => { ws.onopen = res; ws.onerror = () => rej(new Error("WS open 失败")); }); openMs.push(performance.now() - t1); const t2 = performance.now(); ws.send(JSON.stringify({ type: "ping", t: Date.now() })); await new Promise((res) => { const to = setTimeout(() => { rttMs.push(-1); res(); }, 3000); ws.onmessage = () => { clearTimeout(to); rttMs.push(performance.now() - t2); res(); }; }); ws.close(); } catch (err) { openMs.push(-1); console.warn("第" + (i+1) + "次 WS 失败: " + err.message); } } const stat = (a) => { const v = a.filter((x) => x >= 0); if (!v.length) return "全部失败"; const avg = v.reduce((s, x) => s + x, 0) / v.length; return "avg=" + avg.toFixed(1) + "ms min=" + Math.min(...v).toFixed(1) + "ms max=" + Math.max(...v).toFixed(1) + "ms"; }; console.log("目标: " + url + " (" + host + ":" + port + ") x" + times); console.log("TCP连接 : " + stat(tcpMs) + " <- >20ms 查防火墙/IPv6/代理"); if (isWs) { console.log("WS握手 : " + stat(openMs) + " <- >50ms 查服务端WS框架/鉴权"); console.log("消息RTT : " + stat(rttMs) + " <- >50ms 查串行往返/服务端处理"); }