mirror of
https://gitee.com/xmz7891/ykxmz.git
synced 2026-10-18 19:30:42 +00:00
用户报两个问题:
1. 局域网能搜到电脑,IP/端口/配对码都对,点连接**没有任何反应**
2. 走中转 1426ms 延时,一会儿就 502
========== 一、局域网被劫持(真 bug)==========
MainActivity.connect() 里:
boolean usedLan = !relayUrl().isEmpty() ? false : true;
if (!relay.isEmpty()) {
reply = client.connectViaRelay(...); // 走中转
} else {
reply = client.connect(host, port, ...); // 才走局域网
}
**只看「中转设置里填没填地址」,填了就一律走中转,
完全无视用户填的局域网 IP 和端口。**
而中转单次超时是 40 秒 —— 用户点完就卡在「正在连接…」
四十秒,在他看来就是"没有任何反应"。
影响两条路:
* 「局域网连接」页面填 IP 直连(connectLanTyped)
* 首页「已配对的电脑」点一下重连(quickConnect)
修法:给 connect() 加 preferLan 参数。明确要走局域网时
**先直连(6 秒超时,局域网本该是毫秒级),失败再退回中转**,
保证最终能连上。
顺带两个体验改进:
* 设备列表里,保存的 IP 和手表不同网段时标「⚠ 地址可能已过期」
(用户截图里那个 192.168.2.64 就是过期地址,电脑早换成
192.168.10.103 了)
* quickConnect 判断出地址过期就跳过直连,直接走中转查最新地址 ——
省掉那 6 秒白等
========== 二、长轮询 15 秒 -> 60 秒 ==========
实测隧道每次请求要多花 1~2 秒(CF 边缘路由 + 回源):
本机直连 60 秒的 poll -> 60.0s
走公网同一个 poll -> 61.5~62.0s
这个开销是**按次数**收的:
15 秒一循环 -> 一天 5760 次/端,光路费 2.4~3.2 小时
60 秒一循环 -> 一天 1440 次/端,光费 0.6~0.8 小时
而且请求越频繁,撞上丢包/重连窗口的概率越大。
**不会让命令变慢**:长轮询是"有数据立刻返回"(device.event 唤醒),
拉长只是减少空转重开。实测 60 秒长轮询穿隧道 4/4 通过;
Cloudflare 单请求上限 100 秒,留了 40 秒余量。
三层同步改(客户端超时必须显著大于服务端 hold):
* relay/relay.py RELAY_POLL 默认 25 -> 60
* windows/lanremote/relay.py POLL_TIMEOUT 40 -> 90
* android .../RelayTransport.java POLL_TIMEOUT_MS 40000 -> 90000
========== 三、A/B 实测(还在跑更严谨的一轮)==========
短测发现基线 http2+4 虽然 100% 成功,但 **P90 是 16.8 秒**
(每 10 次有 1 次卡十几秒 —— 正是用户说的"没反应"),
而 quic+6 的 P90 只有 2.8 秒。正在用真实长轮询模式
跑 10 分钟对照确认。
103 lines
3.9 KiB
Bash
103 lines
3.9 KiB
Bash
#!/bin/bash
|
|
# 把长轮询从 15 秒拉到 60 秒,实测能不能穿过隧道。
|
|
#
|
|
# 为什么这是核心优化:
|
|
# 隧道每次请求额外加 1~2 秒(连接建立 + CF 内部路由)。
|
|
# 15 秒一循环 -> 一天 5760 次/端,每次都要吃那 1~2 秒。
|
|
# 60 秒一循环 -> 一天 1440 次/端,开销直接摊薄 4 倍。
|
|
#
|
|
# 而且**命令延迟不会变差**:长轮询是"有数据立刻返回",
|
|
# 不是"等满 60 秒才返回"。拉长只是减少空转次数。
|
|
#
|
|
# Cloudflare 对单请求有 100 秒上限(超了 524),60 秒留 40 秒余量。
|
|
set -u
|
|
|
|
BASE=https://relay.xxmxxs.top
|
|
LOCAL=http://127.0.0.1:8080
|
|
UA='LanRemote/1.8.0'
|
|
SVC=/etc/systemd/system/lanremote-relay.service
|
|
BACKUP=/root/lanremote-relay.service.bak.$(date +%s)
|
|
|
|
echo "════════ 1. 备份并改成 60 秒 ════════"
|
|
cp -a "$SVC" "$BACKUP"
|
|
echo " 备份: $BACKUP"
|
|
sed -i 's/^Environment=RELAY_POLL=.*/Environment=RELAY_POLL=60/' "$SVC"
|
|
grep 'RELAY_POLL' "$SVC" | sed 's/^/ /'
|
|
systemctl daemon-reload
|
|
systemctl restart lanremote-relay
|
|
sleep 8
|
|
echo " 中转: $(systemctl is-active lanremote-relay)"
|
|
curl -s --max-time 10 "$LOCAL/v1/health" | head -c 90
|
|
echo
|
|
echo " 等隧道重新连上…"
|
|
for i in $(seq 1 15); do
|
|
c=$(curl -s -o /dev/null -w '%{http_code}' --max-time 12 -H "User-Agent: $UA" "$BASE/v1/health")
|
|
printf " 第 %d 次: %s\n" "$i" "$c"
|
|
[ "$c" = "200" ] && break
|
|
sleep 3
|
|
done
|
|
|
|
echo
|
|
echo "════════ 2. 本机直连(基准,应该约 60 秒)════════"
|
|
DEV="probe60-$(date +%s)"
|
|
REG=$(curl -s --max-time 30 -X POST "$LOCAL/v1/agent/register" \
|
|
-H 'Content-Type: application/json' \
|
|
-d "{\"deviceId\":\"$DEV\",\"code\":\"888888\",\"name\":\"probe60\",\"version\":\"1.8.0\"}")
|
|
TOKEN=$(echo "$REG" | python3 -c "import sys,json; print(json.load(sys.stdin).get('token',''))" 2>/dev/null)
|
|
echo " token ${#TOKEN} 字符"
|
|
for i in 1 2; do
|
|
out=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 120 \
|
|
-X POST "$LOCAL/v1/agent/poll" -H "X-Token: $TOKEN")
|
|
echo " 第 $i 次: $(echo "$out" | awk '{printf "码 %s 耗时 %.1fs", $1, $2}')"
|
|
done
|
|
|
|
echo
|
|
echo "════════ 3. 走公网(关键)════════"
|
|
ok=0
|
|
for i in 1 2 3 4; do
|
|
out=$(curl -s -o /dev/null -w '%{http_code} %{time_total}' --max-time 130 \
|
|
-X POST "$BASE/v1/agent/poll" -H "X-Token: $TOKEN" -H "User-Agent: $UA")
|
|
code=$(echo "$out" | awk '{print $1}')
|
|
secs=$(echo "$out" | awk '{printf "%.1f", $2}')
|
|
printf " 第 %d 次: 码 %-4s 耗时 %ss" "$i" "$code" "$secs"
|
|
if [ "$code" = "200" ]; then
|
|
echo " ✓"
|
|
ok=$((ok + 1))
|
|
elif [ "$code" = "524" ]; then
|
|
echo " **Cloudflare 100 秒上限挡了**"
|
|
else
|
|
echo " ✗"
|
|
fi
|
|
sleep 1
|
|
done
|
|
echo " 成功 $ok/4"
|
|
|
|
echo
|
|
echo "════════ 4. 顺便测「有数据时立刻返回」有没有退化 ════════"
|
|
echo " (往队列里塞点东西,看 poll 是不是马上就回来)"
|
|
# 用 client 侧塞:先建会话太麻烦,改成直接看日志时间戳
|
|
echo " 跳过(需要完整会话,后面用真机验证)"
|
|
|
|
echo
|
|
echo "════════ 5. 结论 ════════"
|
|
if [ "$ok" -ge 3 ]; then
|
|
echo " ✓ 60 秒长轮询能在隧道上跑通,可以改成这个值"
|
|
else
|
|
echo " ✗ 60 秒撑不住,回滚到 15 秒"
|
|
cp -a "$BACKUP" "$SVC"
|
|
systemctl daemon-reload
|
|
systemctl restart lanremote-relay
|
|
echo " 已回滚"
|
|
fi
|
|
|
|
echo
|
|
echo " 服务端设定现在是: $(grep -o 'RELAY_POLL=[0-9]*' "$SVC")"
|
|
echo " 日志: $(tail -30 /root/lanremote-relay/relay.log | grep '长轮询' | tail -1)"
|
|
|
|
echo
|
|
echo "════════ 6. 清掉临时设备 ════════"
|
|
KEY=$(cat /root/lanremote-relay/data/admin_key.txt 2>/dev/null)
|
|
curl -s --max-time 20 -X POST "$LOCAL/v1/admin/delete" -H "X-Admin: $KEY" \
|
|
-H 'Content-Type: application/json' -d "{\"deviceId\":\"$DEV\"}" | head -c 80
|
|
echo
|