为什么接收到的 WebSocket 数据会变成缓冲区?

14

我正在尝试做一个非常基本的WebSocket,但我不明白为什么我没有收到字符串返回。

我正在使用npm中的ws模块作为服务器。https://github.com/websockets/ws

客户端:

    let socket = new WebSocket('wss://upload.lospec.com');

    socket.addEventListener('open', function (event) {
        socket.send('test');
    });

服务器:
const wss = new WebSocket.Server({ server });

wss.on("connection", function (ws) {
    ws.on("message", function (asdfasdf) {
        console.log("got new id from client",asdfasdf);
    });

服务器结果:

got new id from client <Buffer 74 65 73 74>

我试图按照文档和这个教程的示例 https://ably.com/blog/web-app-websockets-nodejs 进行操作。

但它并没有像两个地方承诺的那样输出字符串。

为什么它不是一个字符串?

4个回答

34
你可能使用的是与教程不同版本的ws。教程似乎使用的是早于v8版本的版本,而你使用的是v8+版本。 根据8.0.0版的更改日志: 文本消息和关闭原因不再解码为字符串。它们作为Buffer传递到各自事件的侦听器中。 “message”事件的侦听器现在需要一个布尔参数,指定消息是否为二进制(e173423)。 现有的代码可以通过显式解码缓冲区来迁移。
websocket.on('message', function message(data, isBinary) {
  const message = isBinary ? data : data.toString();
  // Continue as before.
});
websocket.on('close', function close(code, data) {
  const reason = data.toString();
  // Continue as before.
});
这也描述了解决方案。 或者,您可以降级到版本7.5.0的ws,以达到与教程使用的版本相同的水平。
npm i ws@7.5.0

关于库文档中的示例“发送和接收文本数据”,我认为当v8发布时他们没有更新这个示例是一个疏忽。您可以在GitHub上开启问题以让他们知道。


谢谢,那很有道理(现在似乎确实可以工作了)。 - stackers
1
我也想知道文档示例中的%s部分是否自动强制转换为字符串,这就是为什么不需要toString的原因(我怀疑JSON.stringify也是这样做的,我已经看到有几次排除了toString)。 - stackers
即使如此,这个例子也会误导人,正如从这个问题中显而易见的那样。 - CherryDT
除了 Github 存储库之外,您是否知道有官方文档介绍这个问题?我在此或者 WebSocket 的 React 版本中都找不到任何信息。 - Martin Watson
1
你的意思是什么?_官方_的GitHub存储库已经有了_官方_文档(https://github.com/websockets/ws),为什么还需要另一个呢? - CherryDT
@stackers 感谢您的编辑建议,但这是来自更改日志的引用,因此更改它没有意义。此外,逻辑似乎是正确的 - 如果它是二进制的,则无法正确地转换为字符串,因此应该保留为缓冲区;否则将被转换为字符串。 - CherryDT

0
在最新版本中,打印接收到的消息时需要提供%s。以下是来自官方页面npm websocket official page的简单代码片段。
ws.on('message', function message(data) {
  console.log('received: %s', data);
});

0
如果您使用console.log(` ${data} `),它将不会显示<Buffer。但是,如果您使用console.log(data),它将显示<Buffer。例如:
    ws.on('message',data=>{
        console.log(`user sended:${data}`)
    })

这可能是一个错误,或者可以说是正常现象。

修改方法:

    ws.on('message',data=>{
        data=data.toString()
        console.log("user sended:",data)
    })

或者

    ws.on('message',data=>{
        console.log("user sended:",data.toString())
    })

1
这不是一个 bug,只是因为在一个情况下你通过在模板字面量中使用它来强制将其转换为字符串,在另一个情况下则没有。 - CherryDT

0

我曾经遇到过同样的问题。后来发现是因为ws的版本问题。
于是,我安装了另一个版本的ws

你可以试试这个方法:

npm i ws@7.5.0 

在我的情况下它起作用了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接