#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 纯 Python NTP 测速脚本(全球版 2026) 只依赖 ntplib,无任何系统依赖 国内 + 全球通用 Anycast 服务器 """ import asyncio from concurrent.futures import ThreadPoolExecutor import time import socket from typing import Optional, Dict import ntplib # ==================== NTP 服务器列表(国内 + 全球通用) ==================== SERVERS = [ # ==================== 国内主流 ==================== "ntp.aliyun.com", "ntp1.aliyun.com", "ntp2.aliyun.com", "ntp3.aliyun.com", "ntp4.aliyun.com", "ntp5.aliyun.com", "ntp6.aliyun.com", "ntp7.aliyun.com", "time1.aliyun.com", "time2.aliyun.com", "time3.aliyun.com", "time4.aliyun.com", "ntp.tencent.com", "ntp1.tencent.com", "ntp2.tencent.com", "ntp3.tencent.com", "ntp4.tencent.com", "ntp5.tencent.com", "ntp.myhuaweicloud.com", "ntp.baidu.com", "ntp.tuna.tsinghua.edu.cn", "ntp.ntsc.ac.cn", "ntp.sjtu.edu.cn", "ntp.neu.edu.cn", "ntp.bupt.edu.cn", "s1a.time.edu.cn", # ==================== 全球通用 Anycast NTP(重点新增) ==================== "time.cloudflare.com", # Cloudflare(全球最推荐) "time.google.com", "time1.google.com", "time2.google.com", "time3.google.com", "time4.google.com", # Google(带 leap smearing) "time.windows.com", # Microsoft "time.apple.com", # Apple "time.facebook.com", "time1.facebook.com", "time2.facebook.com", # Meta/Facebook "0.pool.ntp.org", "1.pool.ntp.org", "2.pool.ntp.org", "3.pool.ntp.org", "pool.ntp.org", # NTP Pool 全球 ] TIMEOUT = 2.5 # 稍增加超时,照顾全球服务器 def query_ntp(server: str) -> Optional[Dict]: """单个服务器查询""" try: ip = socket.gethostbyname(server) except Exception: ip = "DNS解析失败" try: client = ntplib.NTPClient() response = client.request(server, version=4, timeout=TIMEOUT) return { "server": server, "ip": ip, "delay_ms": round(response.delay * 1000, 3), "offset": round(response.offset, 6), "stratum": response.stratum, } except Exception: return None async def main(): print("🔥 纯 Python NTP 测速工具(国内 + 全球通用版)启动...") print("------------------------------------------------------------------") print(f"{'延迟(ms)':<10} | {'偏移(s)':<12} | {'Stratum':<8} | 服务器 (IP)") print("------------------------------------------------------------------") start_time = time.time() with ThreadPoolExecutor(max_workers=15) as executor: # 增加并发,适应更多服务器 loop = asyncio.get_running_loop() tasks = [loop.run_in_executor(executor, query_ntp, s) for s in SERVERS] results = await asyncio.gather(*tasks) # 过滤成功结果并排序(按延迟升序) successful = [r for r in results if r is not None] successful.sort(key=lambda x: x["delay_ms"]) # 输出 for r in successful: print(f"{r['delay_ms']:<10.3f} | {r['offset']:<12.6f} | {r['stratum']:<8} | " f"{r['server']} ({r['ip']})") failed_count = len(SERVERS) - len(successful) if failed_count > 0: print("------------------------------------------------------------------") print(f"❌ 超时/失败服务器:{failed_count} 个(已自动过滤)") print("------------------------------------------------------------------") total_time = time.time() - start_time print(f"✅ 测速完成!共测试 {len(SERVERS)} 个服务器,用时 {total_time:.2f} 秒") print(" 建议选择顶部 **延迟最低 + Stratum 最小** 的服务器") print(" (国内服务器延迟通常更低,全球服务器可作为备用)") if __name__ == "__main__": asyncio.run(main())