如何测试url延迟

Monkeypox 2026-08-12 10:31 1

延迟好像有很多种,什么ping,tcping,url,真延迟什么的,我感觉比较能真实反应上网体验的应该是url延迟吧,但是那些软件里测的一般不是url延迟,请问如何测试url延迟

最新回复 (2)
  • 35后就失业 08-12 10:35
    1

    tcping 就是你理解的url延迟吧?

  • xSeek 08-12 11:04
    2

    我自己用的。


    import subprocess
    import sys
    import os

    # ANSI 颜色转义码
    RED = "\033[31m"
    GREEN = "\033[32m"
    YELLOW = "\033[33m"
    CYAN = "\033[36m"
    BOLD = "\033[1m"
    RESET = "\033[0m"

    def get_display_width(s):
    """计算字符串实际显示宽度(中文字符算2个宽度)"""
    width = 0
    for char in s:
    if '\u4e00' <= char <= '\u9fff' or '\u3000' <= char <= '\u303f' or '\uff00' <= char <= '\uffef':
    width += 2
    else:
    width += 1
    return width

    def pad_string(s, width):
    """中英文混排字符串填充到指定宽度(中文字符算2个宽度)"""
    display_width = get_display_width(s)
    padding = width - display_width
    if padding > 0:
    return s + ' ' * padding
    else:
    return s

    def test_proxy(tasks):
    # curl 格式化参数
    fmt = "%{time_namelookup} %{time_connect} %{time_appconnect} %{time_starttransfer} %{time_total}"

    print("") # 开头空行

    # 收集所有结果用于最后汇总
    summary = []

    for port, url, desc in tasks:
    # 核心逻辑:没写协议则强制补全 https,写了则完全保留原样(支持自定义协议和端口)
    target_url = url if "://" in url else f"https://{url}"

    if desc:
    print(f"{GREEN}描述 {desc}{RESET}")
    print(f"{CYAN}代理 {port}{RESET}")
    print(f"{CYAN}目标 {target_url}{RESET}")

    try:
    cmd = ["curl.exe", "-x", f"socks5h://127.0.0.1:{port}", "-o", "NUL", "-s", "-w", fmt, "--connect-timeout", "5", target_url]
    result = subprocess.run(cmd, capture_output=True, text=True, timeout=12)

    if result.returncode != 0:
    print(f"{RED}❌ 失败: 代理 {port} 连不通或目标超时 (Code: {result.returncode}){RESET}\n")
    summary.append([
    desc if desc else "-",
    port,
    target_url,
    "失败",
    999999,
    "-",
    999999,
    "-",
    999999,
    "-",
    999999,
    "-",
    999999
    ])
    continue

    # 转换毫秒并保留两位小数
    t = [round(float(x) * 1000, 2) for x in result.stdout.strip().split(" ")]
    pure_response = round(t[3] - t[2], 2)
    dns_time = t[0]
    tcp_time = t[1]
    tls_time = t[2]
    total_time = t[4]

    print(f"DNS 解析 {dns_time} ms")
    print(f"TCP 建立 {tcp_time} ms")
    print(f"TLS 握手 {tls_time} ms")
    # 红色标记纯响应时间
    print(f"纯响应 {RED}{pure_response} ms{RESET} (减去握手耗时)")
    print(f"首字节 {t[3]} ms (TTFB)")
    print(f"总计耗时 {total_time} ms")
    print("")

    summary.append([
    desc if desc else "-",
    port,
    target_url,
    f"{total_time} ms",
    total_time,
    f"{pure_response} ms",
    pure_response,
    f"{dns_time} ms",
    dns_time,
    f"{tcp_time} ms",
    tcp_time,
    f"{tls_time} ms",
    tls_time
    ])

    except Exception as e:
    print(f"{RED}❌ 异常: {e}{RESET}\n")
    summary.append([
    desc if desc else "-",
    port,
    target_url,
    "异常",
    999999,
    "-",
    999999,
    "-",
    999999,
    "-",
    999999,
    "-",
    999999
    ])

    # 输出汇总排名(只在共用模式下,即所有任务共用一个 URL)
    urls = set(task[1] for task in tasks)
    if len(urls) == 1 and len(summary) > 1:
    # 按总计耗时排序(数值从小到大,失败/异常的999999会排到最后)
    summary.sort(key=lambda x: x[4])

    # 定义表头
    headers = ["描述", "端口", "网址", "总计耗时", "纯响应(类ping)", "DNS", "TCP", "TLS"]

    # 动态计算每列最大显示宽度
    col_widths = []
    for i, header in enumerate(headers):
    max_width = get_display_width(header)
    for item in summary:
    if i == 0: # 描述
    width = get_display_width(item[0])
    elif i == 1: # 端口
    width = get_display_width(item[1])
    elif i == 2: # 网址
    width = get_display_width(item[2])
    elif i == 3: # 总计耗时
    width = get_display_width(item[3])
    elif i == 4: # 纯响应(类ping)
    width = get_display_width(item[5])
    elif i == 5: # DNS
    width = get_display_width(item[7])
    elif i == 6: # TCP
    width = get_display_width(item[9])
    elif i == 7: # TLS
    width = get_display_width(item[11])
    max_width = max(max_width, width)

    # 最小宽度限制
    min_widths = [12, 8, 20, 10, 14, 8, 8, 8]
    col_widths.append(max(max_width, min_widths[i]))

    # 列间距2个空格
    col_gap = 2

    # 计算总宽度
    total_width = sum(col_widths) + col_gap * (len(headers) - 1)

    print(f"{'='*total_width}")
    print(f"📊 总计耗时排名(由快到慢)")
    print(f"{'='*total_width}")

    # 打印表头
    header_line = ""
    for i, header in enumerate(headers):
    if i > 0:
    header_line += ' ' * col_gap
    header_line += pad_string(header, col_widths[i])
    print(header_line)

    print(f"{'-'*total_width}")

    # 打印数据行
    rank = 1
    for item in summary:
    desc = item[0]
    port = item[1]
    url = item[2]
    total_time_str = item[3]
    total_time_val = item[4]
    pure_response_str = item[5]
    dns_str = item[7]
    tcp_str = item[9]
    tls_str = item[11]

    # 构建每列数据
    cols = [
    desc,
    port,
    url,
    total_time_str,
    pure_response_str,
    dns_str,
    tcp_str,
    tls_str
    ]

    # 拼接行
    line = ""
    for i, col in enumerate(cols):
    if i > 0:
    line += ' ' * col_gap
    line += pad_string(col, col_widths[i])

    # 失败/异常用红色显示
    if total_time_val == 999999:
    print(f"{RED}{rank}. {line}{RESET}")
    elif rank == 1:
    # 第一名用绿色
    print(f"{GREEN}{rank}. {line}{RESET}")
    else:
    print(f"{rank}. {line}")
    rank += 1

    print(f"{'='*total_width}\n")

    if __name__ == "__main__":
    if sys.platform == "win32":
    os.system("")

    if len(sys.argv) < 2:
    print(f"\n{BOLD}{YELLOW}[用法1]{RESET} {GREEN}独立模式{RESET}: python url-Test.py {CYAN}代理端口1 网址1{RESET},{CYAN}代理端口2 网址2{RESET}")
    print(f" {BOLD}{YELLOW}注意:{RESET} 独立模式仅支持英文逗号分隔多组任务,空格为端口与网址的分隔符")
    print(f"\n{BOLD}{YELLOW}[用法2]{RESET} {GREEN}共用模式{RESET}: python url-Test.py {CYAN}端口1{RESET} -w {CYAN}网址{RESET}")
    print(f"{BOLD}{YELLOW}[用法2]{RESET} {GREEN}共用模式{RESET}: python url-Test.py -w {CYAN}网址{RESET} {CYAN}端口1 端口2 端口3{RESET}")
    print(f" {BOLD}{YELLOW}注意:{RESET} {BOLD}{RED}仅 -w 共用模式{RESET}支持端口用英文逗号、中文逗号、空格混用分隔")
    print(f" {BOLD}{YELLOW}端口描述:{RESET} -w 模式下支持 {CYAN}端口-描述{RESET} 格式,如 {CYAN}907-香港 800-日本{RESET}")
    print(f"\n{BOLD}{YELLOW}[分隔符支持]:{RESET}")
    print(f" {GREEN}-w 共用模式:{RESET} 英文逗号({CYAN},{RESET})、中文逗号({CYAN},{RESET})、空格 混用")
    print(f" 示例: {CYAN}700,8000,600 8001{RESET} 均可正确解析")
    print(f" {GREEN}独立模式:{RESET} 仅支持英文逗号({CYAN},{RESET})分隔多组任务")
    print(f"\n{BOLD}{YELLOW}[自动补全逻辑]:{RESET}")
    print(f" 1. 纯域名 ({CYAN}a.com{RESET}) -> 自动补全为 {CYAN}https://{RESET} (443端口)")
    print(f" 2. 带协议 ({CYAN}http://a.com:1688{RESET}) -> 保持原样 (使用指定协议和端口)")
    print(f"\n{BOLD}{YELLOW}[独立模式示例]:{RESET}")
    print(f" python url-Test.py {CYAN}1205 wap.nkcc.com{RESET},{CYAN}8501 gg.nkcc.com{RESET},{CYAN}1203 alice.nkcc.com{RESET}")
    print(f"\n{BOLD}{YELLOW}[共用模式示例]:{RESET}")
    print(f" python url-Test.py {CYAN}700,8000,600{RESET} -w {CYAN}alice.nkcc.com{RESET}")
    print(f" python url-Test.py -w {CYAN}alice.nkcc.com{RESET} {CYAN}700 8000 600{RESET}")
    print(f" python url-Test.py -w {CYAN}http://www.nodeseek.com{RESET} {CYAN}907-halo 800-zouter 4000-光帆 700-菠萝云 {RESET}")
    sys.exit(0)

    # 解析参数,找 -w 位置
    full_input = " ".join(sys.argv[1:])
    args = sys.argv[1:]

    # 检查是否使用共用模式(有 -w 参数)
    url_index = -1
    try:
    url_index = args.index("-w")
    except ValueError:
    pass

    if url_index != -1:
    # 共用模式:-w 参数存在
    if url_index + 1 >= len(args):
    print(f"\n{RED}错误: -w 后缺少网址参数{RESET}\n")
    sys.exit(1)

    common_url = args[url_index + 1]

    # 端口列表在 -w 的前面或后面
    ports_str = ""
    if url_index > 0:
    # -w 在后面,端口在前面
    ports_str = " ".join(args[:url_index])
    elif url_index + 2 < len(args):
    # -w 在前面,端口在后面
    ports_str = " ".join(args[url_index + 2:])

    if not ports_str:
    print(f"\n{RED}错误: 未提供端口列表{RESET}\n")
    sys.exit(1)

    # 解析端口(支持英文逗号、中文逗号、空格混用)
    # 先把中文逗号替换成英文逗号,再统一处理
    ports_str = ports_str.replace(",", ",")

    # 按逗号或空格分割成独立项
    items = []
    for item in ports_str.replace(",", " ").split():
    item = item.strip()
    if item:
    items.append(item)

    # 构建任务列表,支持端口-描述格式
    all_tasks = []
    for item in items:
    if "-" in item:
    parts = item.split("-", 1) # 只分割第一个"-"
    port = parts[0]
    desc = parts[1]
    else:
    port = item
    desc = ""
    all_tasks.append([port, common_url, desc])

    if not all_tasks:
    print(f"\n{RED}错误: 端口解析失败{RESET}\n")
    sys.exit(1)
    else:
    # 独立模式:原逻辑
    groups = [g.strip() for g in full_input.split(",") if g.strip()]
    all_tasks = []

    for group in groups:
    parts = group.split()
    if len(parts) >= 2:
    all_tasks.append([parts[0], parts[1], ""]) # 独立模式无描述

    if not all_tasks:
    print(f"\n{RED}错误: 参数解析失败。{RESET}\n")
    sys.exit(1)

    test_proxy(all_tasks)
* 帖子来源NodeSeek
返回