WebSocket 在线测试
连接 / 收发 / 心跳 · 浏览器本地
连接/收发/心跳测试
连接 / 收发 / 心跳 · 浏览器本地
了解工具定位 · 使用场景 · 对比优势
前端开发者在对接实时推送接口时,后端文档只说「连接 ws://xxx 后监听 message 事件」。用本工具直接输入后端地址,一键建立连接,手动发送 JSON 格式的订阅消息,实时查看服务端返回的原始数据帧,快速定位字段名拼写错误或数据类型不匹配问题,无需写测试代码。
物联网设备通过 WebSocket 上报传感器数据,但设备端每隔 60 秒需发一次 ping 帧维持连接。运维人员用本工具连接设备网关,手动发送心跳包并观察服务端是否回复 pong,验证网关的心跳超时策略是否按预期断开僵尸连接,避免因连接池占满导致新设备无法接入。
第三方支付回调使用 WebSocket 推送交易结果,但对方服务器只支持 wss 且要求特定 subprotocol。测试人员用本工具填写 wss 地址和 subprotocol 头,连接后发送模拟的支付成功报文,检查服务端是否按约定返回 ack 帧,确认跨域名、跨协议栈的握手流程没有异常。
安全审计时怀疑 WebSocket 连接存在 CSRF 漏洞,攻击者可能利用未校验 Origin 头的漏洞劫持连接。用本工具构造不同 Origin 头的连接请求,观察服务端是否拒绝非法来源,验证 CORS 配置是否生效,确保只有白名单域名能建立 WebSocket 通道。
| 维度 | 本工具 | 竞品 A (PieSocket) | 传统方法 (命令行) |
|---|---|---|---|
| 连接配置 | 支持 URL 输入,可选子协议、自定义请求头 | 提供 SDK/API,需集成代码 | 需手写脚本,如 wscat、websocat |
| 心跳测试 | 内置 Ping/Pong 帧发送与响应检测 | 需自行实现心跳逻辑 | 需手写脚本处理帧 |
| 收发消息 | 可视化输入框,支持 JSON/文本/十六进制 | 通过 SDK 事件监听 | 需解析命令行输出 |
| 数据隐私 | 纯浏览器处理,无服务器中转 | 数据经过 PieSocket 服务器 | 数据直连目标服务器 |
| 离线可用 | 页面加载后完全离线可用 | 依赖网络 API 服务 | 依赖本地安装的工具包 |
| 使用门槛 | 零安装,浏览器打开即用 | 需注册账号、阅读文档 | 需安装命令行工具并了解协议 |
| 并发连接 | 单页面单连接 | 支持多连接管理 | 可脚本化多连接 |
上手步骤 · 输入输出 · 避坑提示
| 输入 | 输出 | 说明 |
|---|---|---|
| wss://echo.websocket.org | 连接成功 | 收到服务端回复: 你发送的消息 | 典型场景:公共回显服务,验证基本连接与收发 |
| ws://localhost:8080/chat | 连接成功 | 等待服务端消息 | 典型场景:本地开发调试 WebSocket 服务 |
| wss://stream.binance.com:9443/ws/btcusdt@trade | 连接成功 | 收到实时交易数据(JSON 格式) | 典型场景:连接公开数据流,验证实时推送 |
| ws://192.168.1.100:9000 | 连接失败: 连接超时 (30s) | 边界 case:目标 IP 不可达或端口未开放 |
| wss://invalid.example.com/ws | 连接失败: DNS 解析错误 | 边界 case:域名不存在或 DNS 配置错误 |
| ws://127.0.0.1:65536 | 连接失败: 端口号超出范围 (0-65535) | 易错 case:端口号超过最大允许值 |
| wss://echo.websocket.org (发送空消息) | 发送成功 | 收到空字符串回复 | 易错 case:空消息是否被视为合法数据帧 |
连续点击连接按钮 3 次,不先断开已有连接每次连接前先点击断开按钮,或等待连接自动关闭后再新建连接WebSocket 协议要求同一客户端在同一时间只维持一个连接;重复连接会导致旧连接被服务端丢弃或双方状态不一致。
在消息输入框直接粘贴一个 .png 文件的二进制内容(乱码)将二进制数据用 Base64 编码后发送,并在应用层约定解码方式WebSocket 支持二进制帧,但浏览器发送框通常只接受文本字符串;直接粘贴二进制会丢失字节完整性或触发编码错误。
心跳间隔设为 500 毫秒(0.5 秒)心跳间隔设为 30 秒到 60 秒之间高频心跳包会被服务端视为攻击性行为(DDoS 或探测),许多网关和 WAF 会直接断开连接或封禁 IP。
在 https://websocket.tl654.com/ 页面输入 ws://echo.websocket.org在 https 页面使用 wss://echo.websocket.org 或使用 ws:// 地址时需确保页面也是 http浏览器安全策略禁止 HTTPS 页面发起不安全的 WebSocket 连接(混合内容阻止),控制台会报 Mixed Content 错误。
只输入 ws://example.com 不写路径ws://example.com/ws 或 ws://example.com/socket.io/?EIO=4&transport=websocketWebSocket 握手需要完整 URL(包括路径和查询参数);服务端通常根据路径分发到不同 handler,缺路径会 404 或 400。
直接输入 { "action": "ping", "ts": 1234567890 } 作为纯文本先确认服务端期望的是 JSON 字符串还是纯文本;若期望 JSON 则直接发送序列化后的字符串WebSocket 消息本身是二进制或文本帧,不自动解析 JSON;服务端收到的是字符串,需自行 JSON.parse。若服务端期望 JSON 但收到非 JSON 字符串会解析失败。
点击断开按钮后不查看关闭帧的状态码和原因观察关闭事件中的 code(如 1000 正常关闭、1006 异常断开)和 reason 字段关闭帧的 code 和 reason 是排查连接异常的关键线索;1006 表示连接意外断开(网络/超时),1001 表示服务端主动关闭。
服务端期望 ping/pong 帧,却发送自定义文本 "keepalive"查阅服务端文档,确认心跳机制是 WebSocket 协议层的 ping/pong 帧还是应用层的自定义消息WebSocket 协议自带 ping/pong 控制帧(浏览器 API 不暴露),很多服务端用应用层消息做心跳;两者不匹配会导致心跳失效。
公式推导 · 流程图解 · 依据出处
RTT = T_ack - T_send
RTT — 往返时延(毫秒)T_send — 数据包发送时刻(毫秒时间戳)T_ack — 对应确认帧接收时刻(毫秒时间戳)向 wss://echo.websocket.org 发送一条文本消息 'ping',记录发送时刻 T_send = 1712345678000 ms。服务器原样返回 'ping',收到时刻 T_ack = 1712345678120 ms。RTT = 1712345678120 - 1712345678000 = 120 ms。
适用于 WebSocket 协议标准(RFC 6455)下的单次消息往返时延测量。不适用于分片消息、多帧合并或存在代理缓冲的场景,此时 RTT 可能包含中间节点处理延迟。
3 种主流语言 · 复制即用
import asyncio
import websockets
async def test_websocket():
uri = "wss://echo.websocket.org"
async with websockets.connect(uri) as ws:
# 发送消息
await ws.send("Hello WebSocket")
# 接收回显
response = await ws.recv()
print(f"Received: {response}")
# 心跳测试:发送 ping 并等待 pong
pong = await ws.ping()
await pong
print("Pong received, connection alive")
asyncio.run(test_websocket())package main
import (
"fmt"
"net/url"
"github.com/gorilla/websocket"
"log"
)
func main() {
u := url.URL{Scheme: "wss", Host: "echo.websocket.org", Path: ""}
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatal("dial:", err)
}
defer c.Close()
// 发送消息
err = c.WriteMessage(websocket.TextMessage, []byte("Hello WebSocket"))
if err != nil {
log.Fatal("write:", err)
}
// 接收回显
_, message, err := c.ReadMessage()
if err != nil {
log.Fatal("read:", err)
}
fmt.Printf("Received: %s\n", message)
// 心跳测试:发送 Pong 帧(服务端通常回复 Ping)
err = c.WriteMessage(websocket.PongMessage, []byte("keepalive"))
if err != nil {
log.Fatal("pong:", err)
}
fmt.Println("Heartbeat sent")
}const ws = new WebSocket('wss://echo.websocket.org');
ws.onopen = () => {
console.log('Connected');
// 发送消息
ws.send('Hello WebSocket');
// 心跳:发送 ping(浏览器 WebSocket API 自动处理 pong)
// 可手动发送空消息作为心跳
setInterval(() => {
if (ws.readyState === WebSocket.OPEN) {
ws.send('ping');
}
}, 30000);
};
ws.onmessage = (event) => {
console.log('Received:', event.data);
};
ws.onerror = (error) => {
console.error('WebSocket error:', error);
};8 个高频疑问
「HTTP / 网络速查」下的其他工具