我正在使用节点 ws 库(Ubuntu 16.04 上的节点 10.8.0)连接到外部 websocket api。我有一个监听器只是解析 json 并将其传递给回调:
this.ws.on('message', (rawdata) => {
let data = null;
try {
data = JSON.parse(rawdata);
} catch (e) {
console.log('Failed parsing the following string as json: ' + rawdata);
return;
}
mycallback(data);
});
我现在收到错误,其中rawData
看起来如下(我格式化并删除了不相关的内容):
�~A
{
"id": 1,
etc..
}�~�
{
"id": 2,
etc..
然后我想知道;这些人物是什么?看到结构我最初认为第一个奇怪的符号必须是数组的开始括号([
),第二个是逗号(,
),以便它创建一个对象数组。
然后,每当遇到 JSON 解析错误时,都会通过将rawdata
写入文件来进一步调查问题。在一个小时左右的时间里,它已经保存了大约 1500 个错误文件,这意味着这种情况会发生很多。我在终端上编辑了几个这样的文件,其中我上传了一个例子:
这里有一些有趣的事情:
-
文件始终以这些奇怪的标志之一开始。
-
这些文件似乎存在于应该单独接收的多条消息中。奇怪的标志将这些个别信息分开。
-
文件总是以未完成的 json 对象结束。
-
文件的长度各不相同。它们的尺寸并不总是相同,因此不会在特定长度上切断。
我对 websockets 不太熟悉,但可能是因为我的 websocket 以某种方式接收到它连接在一起的消息流,这些奇怪的符号作为分隔符,然后随机切断最后一条消息?也许是因为我得到了一个非常快速的消息流?
或者可能是因为服务器端的错误(或功能),它组合了这些单独的消息?
有谁知道这里发生了什么?欢迎所有提示!
[编辑]
_1_suggested 将其解释为 utf8。所以我做了,我粘贴了下面结果的截图。第一个打印是原样,第二个打印为 utf8。对我来说这看起来不像什么。我当然可以转换为 utf8,然后按这些字符拆分。虽然最后一条消息总是被切断,但这至少会使一些消息变得可读。其他想法仍然欢迎。
4 回答
我的假设是你只使用了 English/ASCII 个字符而且可能搞乱了流。 (NOTE:I am am),没有特殊字符,如果是这样,那么我建议你将整个 json 字符串传递给这个函数:
你可以参考如何从 JavaScript 字符串中删除无效的 UTF-8 字符?
编辑
来自互联网工程任务组(IETF)的文章,
“有效载荷数据”是编码为 UTF-8 的文本数据。请注意,特定文本框架可能包含部分 UTF-8 序列;但是,整个消息必须包含有效的 UTF-8。重组消息中的无效 UTF-8 按照_处理 UTF-8-Encoded 数据**中的错误中的描述进行处理,其中指出当端点将字节流解释为 UTF-8 但发现字节流实际上不是有效的 UTF-8 流时,该端点必须_Fail WebSocket Connection_。此规则适用于打开握手期间和后续数据交换期间。
我真的相信你的错误(或功能)来自服务器端,它结合了你的个人消息,因此我建议你提出一个逻辑,确保你的所有角色**必须首先从 Unicode 转换为 ASCII 将字符编码为 UTF-8。并且您可能还希望安装
npm install --save-optional utf-8-validate
以有效地检查消息是否包含规范要求的有效 UTF-8。您可能还希望传入
if
条件来帮助您进行一些检查;我希望这会有所帮助。
看来您的输出有一些空格,如果您有任何空格或者如果您发现任何特殊字符,请使用 Unicode 来完全填充它们。
这是 Unicode 字符列表
这可能对我有所帮助。
这些字符称为“替换字符” - 用于替换未知,未识别或不可表示的字符。
来自:https://en.wikipedia.org/wiki/Specials_(Unicode_block)
检查WebSocket 协议错误处理的第 8 部分:
8.1. 从服务器处理 UTF-8 中的错误
当客户端将字节流解释为 UTF-8 但发现字节流实际上不是有效的 UTF-8 流时,任何无效 UTF-8 序列的字节或字节序列必须被解释为 U FFFD REPLACEMENT CHARACTER。
8.2. 从客户端处理 UTF-8 中的错误
当服务器将字节流解释为 UTF-8 但发现字节流实际上不是有效的 UTF-8 流时,行为是未定义的。服务器可以关闭连接,将无效字节序列转换为 U FFFD REPLACEMENT CHARACTER,逐字存储数据或执行 application-specific 处理。在 WebSocket 协议上分层的子协议可以定义服务器的特定行为。
取决于正在使用的实现或库如何处理这个,例如从这篇文章使用 Node.js 实现 Web 套接字服务器:
在这种情况下,如果找到
�
,它将执行:您可以做的另一件事是将节点更新到最新的稳定版,从这篇帖子OpenSSL 和 Breaking UTF-8 Change(在 Node v0.8.27 和 v0.10.29 中修复):
尝试使用以下代码解决此问题:
或者
utf16
:请阅读:字符串解码器文档