
本文旨在解决在使用原生 WebSocket 连接 SignalR Hub 时,客户端无法接收到服务端推送消息的问题。文章将分析可能的原因,并提供一种通过修改 SignalR 库的导入方式来解决问题的方案,从而避免使用 SignalR 库时出现的构建错误。
当尝试使用 WebSocket 直接连接 SignalR Hub 时,可能会遇到 onmessage 事件未触发,导致无法接收服务端消息的问题。虽然 onopen 事件能够正常触发,表明 WebSocket 连接已经建立,但消息却无法正确传递。以下提供一种可能的解决方案,以及一些排查思路。
问题分析
- SignalR 协议协商: SignalR 使用特定的协议进行通信,并非简单的 WebSocket 协议。在建立连接之前,客户端需要与服务端进行协议协商,获取连接所需的 connectionToken。
- 消息格式: SignalR 使用特定的消息格式(通常是 JSON)进行数据传输。如果客户端发送或接收的消息格式不正确,会导致通信失败。
- 库的导入方式: 使用 Rollup 等打包工具时,不同的导入方式可能会影响库的正确加载和使用。
解决方案
如果遇到 default is not exported by @microsoft/signalr 错误,可能是因为导入方式不正确。尝试以下导入方式:
import * as signalR from "@microsoft/signalr";
而不是:
import signalR, { HubConnection } from "@microsoft/signalr";这种导入方式可以避免 Rollup 打包时出现的问题,确保 SignalR 库能够正确加载。
详细步骤
Raza Microelectronics, Inc.(RMI公司)是勇于创新的信息基础架构半导体解决方案领导厂商,其产品广泛地被应用于改善不断演进的信息基础设施。在这个演进过程中,数据中心和家庭之间的连接在强度和速率方面都逐渐升级;安全和智能化已经成为每一个网络系统环境的要求;同时,边缘网络日益成为瓶颈,促使业界需要更具扩展能力及成本优势的智能网络接入方法。RMI公司为信息基础架构设计并提供多样化的解决方案,为下一代灵活的企业和数据中心应用、智能接入和数字影像系统奠定基础。 RMI远程方法调用目录 一、
-
协议协商: 使用 fetch API 向 /negotiate 端点发送 POST 请求,获取 connectionToken。
let url = "https://localhost:7143/chatHub"; const headers = {}; const [name, value] = getUserAgentHeader(); headers[name] = value; fetch(`${url}/negotiate?negotiateVersion=1`, { method: "POST", headers: { "Content-Type": "application/json", headers, }, body: JSON.stringify({ content: "", headers: headers, timeout: 100000, withCredentials: true, }), }) .then((response) => response.json()) .then((response) => { // The fetch return here some information about signalR connection, and the token for idendification console.log(response); // The web socket for SignalR's connection const wsUrl = `${url}?id=${response.connectionToken}`.replace(/^http/, "ws"); const webSocket = new WebSocket(wsUrl); webSocket.onopen = (event) => { // It's triggered console.log(event); } webSocket.onmessage = (message) => { // It's not triggered console.log(message); } webSocket.onerror = (event) => { console.log(event); console.log(event.error); } webSocket.onclose = (event) => { console.log(event); } }); -
构建 WebSocket URL: 将 connectionToken 附加到 WebSocket URL。
const wsUrl = `${url}?id=${response.connectionToken}`.replace(/^http/, "ws"); -
创建 WebSocket 连接: 使用构建好的 URL 创建 WebSocket 连接。
const webSocket = new WebSocket(wsUrl);
-
处理消息: 确保 onmessage 事件处理函数能够正确解析 SignalR 消息格式。
webSocket.onmessage = (message) => { // 解析 SignalR 消息格式 console.log(message); }
其他注意事项
- 跨域问题: 确保服务端允许跨域请求,否则 WebSocket 连接可能会被阻止。
- 防火墙: 检查防火墙设置,确保 WebSocket 连接没有被阻止。
- 服务端配置: 确保 SignalR Hub 在服务端正确配置,并且正在发送消息。
总结
通过修改 SignalR 库的导入方式,可以解决在使用 Rollup 等打包工具时可能出现的构建错误。同时,需要确保正确进行协议协商,构建 WebSocket URL,并处理 SignalR 消息格式。如果问题仍然存在,可以检查跨域、防火墙和服务端配置等因素。









