# -*- coding: utf-8 -*- r'''把长轮询从 15 秒改成 60 秒(服务端 + 两个客户端同步改)。 == 为什么这是这一轮最有效的优化 == 隧道每次请求要多花 1~2 秒(CF 边缘路由 + 回源)。实测: 本机直连 60 秒的 poll -> 60.0s 走公网隧道同一个 poll -> 61.5~62.0s 只多 1.5~2 秒 看着不多,但**这个开销是按"次数"收的**: 15 秒一循环 -> 一天 5760 次/端 -> 光路费就 2.4~3.2 小时 60 秒一循环 -> 一天 1440 次/端 -> 光路费就 0.6~0.8 小时 而且请求越频繁,"正好撞上丢包/重连窗口"的概率越大。 拉长到 60 秒,暴露面直接降到 1/4。 == 为什么不会让命令变慢 == 长轮询是**有数据立刻返回**(relay.py 里用 device.event 唤醒), 不是"等满 60 秒才看一眼"。拉长超时只是减少"空转重开"的次数, 真正下命令时的延迟不变。 实测 60 秒长轮询穿过隧道 4/4 成功;Cloudflare 单请求上限是 100 秒, 60 秒留了 40 秒余量。 == 要同步改的三处 == 1. relay/relay.py POLL_SECONDS 默认 25 -> 60 2. windows/lanremote/relay.py POLL_TIMEOUT 40 -> 90 3. android .../RelayTransport.java POLL_TIMEOUT_MS 40000 -> 90000 客户端超时必须显著大于服务端 hold 时间,否则会在服务端正常返回之前 自己先超时 —— 那会变成"每次轮询都失败"的灾难。 ''' from __future__ import annotations import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") BOM = b"\xef\xbb\xbf" RELAY_OLD = 'POLL_SECONDS = float(os.environ.get("RELAY_POLL", "25"))' RELAY_NEW = """# 长轮询挂多久。 # 25 -> 60:隧道每次请求要多花 1~2 秒(CF 边缘路由 + 回源), # 而这个开销是按"次数"收的。60 秒一循环把请求数降到 1/4, # 暴露在丢包/重连窗口里的概率也降到 1/4。 # **不会让命令变慢**:有数据时立刻返回(靠 device.event 唤醒), # 拉长只是减少空转重开。 # Cloudflare 单请求上限 100 秒,60 留了 40 秒余量(实测 4/4 通过)。 POLL_SECONDS = float(os.environ.get("RELAY_POLL", "60"))""" AGENT_OLD = "POLL_TIMEOUT = 40.0" AGENT_NEW = """# 长轮询单次请求的超时。 # 必须显著大于服务端的 hold 时间(现在 60 秒),否则会在服务端 # 正常返回之前自己先超时 —— 那就变成"每次轮询都失败"了。 # 90 = 60 + 30 秒余量。 POLL_TIMEOUT = 90.0""" WATCH_OLD = ( " /** 长轮询:中转那边挂 25 秒,客户端超时给宽一点 */\n" " private static final int POLL_TIMEOUT_MS = 40000;" ) WATCH_NEW = ( " /**\n" " * 长轮询:中转那边挂 60 秒,客户端超时给宽一点。\n" " *\n" " *

必须显著大于服务端的 hold 时间,否则会在服务端正常返回\n" " * 之前自己先超时 —— 那就变成\"每次轮询都失败\"了。\n" " * 90 秒 = 60 + 30 秒余量。\n" " */\n" " private static final int POLL_TIMEOUT_MS = 90000;" ) EDITS = [ ("relay/relay.py", RELAY_OLD, RELAY_NEW, "服务端 60 秒"), ("windows/lanremote/relay.py", AGENT_OLD, AGENT_NEW, "被控端 90 秒"), ("android/src/com/lanremote/watch/RelayTransport.java", WATCH_OLD, WATCH_NEW, "手表 90 秒"), ] def main() -> int: print(" 改这三处:") ok_all = True for rel, old, new, label in EDITS: path = ROOT / rel if not path.is_file(): print(" ✗ %s 不存在" % rel) ok_all = False continue raw = path.read_bytes() had_bom = raw.startswith(BOM) text = raw.decode("utf-8-sig") if old not in text: if new.strip().splitlines()[-1] in text: print(" • %-44s 已经是新值了" % rel) continue print(" ✗ %-44s 找不到锚点" % rel) ok_all = False continue count = text.count(old) if count != 1: print(" ! %-44s 锚点出现 %d 次" % (rel, count)) ok_all = False continue text = text.replace(old, new, 1) data = text.encode("utf-8") if had_bom or path.suffix == ".ps1": data = BOM + data path.write_bytes(data) print(" ✓ %-44s 已改" % rel) print() if not ok_all: print(" 有失败项,请检查") return 1 print(" 复核:") checks = [ ("relay/relay.py", 'os.environ.get("RELAY_POLL", "60")'), ("windows/lanremote/relay.py", "POLL_TIMEOUT = 90.0"), ("android/src/com/lanremote/watch/RelayTransport.java", "POLL_TIMEOUT_MS = 90000"), ] for rel, token in checks: text = (ROOT / rel).read_text(encoding="utf-8-sig") print(" %s %s" % ("✓" if token in text else "✗", rel)) return 0 if __name__ == "__main__": sys.exit(main())