WebSocket发送成功但服务器无响应,首要检查帧类型是否为Text而非Binary;其次确认消息格式未嵌套JSON;最后排查Nginx等中间件超时断连及VueUse重连时token未更新问题。

WebSocket发送成功但服务器没响应?先看帧类型是不是Text
浏览器 Network → WS → Frames 标签页里,如果看到你发的帧类型是 Binary,而服务端只监听 @OnMessage 的 String 参数(Java Spring),那消息根本不会进业务逻辑——日志静默,控制台也没报错,纯“石沉大海”。
前端检查点:
-
typeof data === 'string'才调用send();传ArrayBuffer、Blob或TypedArray会自动发二进制帧 - VueUse 的
useWebSocket默认对非字符串数据做二进制处理,sendText.value是字符串,但如果你误把对象直接传给send(),它可能被序列化为[object Object]再发出去——服务器收的是垃圾字符串 - 打开 Frames 面板,确认你发的每一帧右上角标的是
Text,不是Binary或Continuation
消息格式嵌套两层JSON?服务器很可能根本没解析内层
你构造的 jsonMessage 是:{"type":"demo-message-send","content":"{\"text\":\"hi\",\"toUserId\":\"123\"}"}。这要求服务端收到后先 JSON.parse 外层,再对 content 字段再 JSON.parse 一次。但很多后端(尤其 Node.js 原生 ws 库)默认只做一次解析,拿到的就是一个带转义引号的字符串,不是对象。
更常见的服务端预期是扁平结构:
- 正确:直接发
{"type":"demo-message-send","text":"hi","toUserId":"123"} - 错误:发两层 JSON 字符串(即
JSON.stringify({ content: JSON.stringify(...) })) - 验证方法:用
wscat -c ws://192.168.0.87:8080/ws?token=xxx手动连,发原始 JSON 对象,看服务端是否响应
连接显示OPEN,但发消息像丢进黑洞?大概率被中间件悄悄断连了
Nginx、Spring Cloud Gateway、甚至某些云 WAF 默认 60 秒无数据就发 FIN 关闭连接。客户端 socket.readyState === 1 仍是 OPEN,但后续所有 send() 都发不出去——不报错,也不触发 onerror,就是没回音。
WebSocket 8.18.2 是该协议规范的一个重要迭代版本,主要优化了连接稳定性与数据传输效率。它通过全双工通信机制,允许客户端与服务器在单一长连接上实时交换数据,大幅降低传统 HTTP 轮询的开销。该版本增强了心跳保活、自动重连及二进制帧传输能力,适用于即时通讯、在线游戏及金融行情推送等低延迟场景,为开发者提供更可靠的实时网络交互基础。
必须做的三件事:
- 在
onopen后立即启动定时器:setInterval(() => ws.send('ping'), 30000) - 服务端要响应(哪怕只是原样 echo),否则超时仍会断
- 检查 Nginx 配置是否透传了
Upgrade和Connection头,且设置了proxy_read_timeout 300(至少 5 分钟)
Vue3 + useWebSocket 发送没反应?检查 token 是否随重连丢失
你写的 URL:ws://192.168.0.87:8080/ws?token=${refreshToken}。但 useWebSocket 在自动重连时,**不会重新求值 ref**,也就是说第一次连接用的是初始 refreshToken,之后重连永远用那个旧值——认证失败,连接建立后立刻被服务器踢掉,但前端没监听 onclose 码,看不出异常。
解决方案只有两个:
- 不用 URL 拼接 token,改用
onConnected回调里手动发认证消息(如send(JSON.stringify({ type: 'auth', token: refreshToken.value }))) - 自己封装重连逻辑,每次重连前重新生成带新 token 的 URL,而不是依赖
useWebSocket的自动重连
这个坑在 Vue3 组合式函数里特别隐蔽:ref 值变了,但 URL 字符串没变,重连时连的还是过期地址。










