【问题标题】:Using websocket compression with uWebSockets.js and Websocket-Sharp通过 uWebSockets.js 和 Websocket-Sharp 使用 websocket 压缩
【发布时间】:2019-12-04 16:10:19
【问题描述】:

我们有一个使用 websocket 进行连接的手机游戏。服务器是使用 uWebSockets.js 库的 Node.js 应用程序,客户端是使用 Websocket-Sharp 库的 Unity 应用程序。他们俩一起玩得很好,我们没有遇到他们的问题。

最近我们想要启用 websocket 压缩。两个库都表示它们支持 Per-message Compression 扩展,但似乎有一些与它们不兼容的东西。因为当我们配置为使用压缩时,websocket 连接会在握手时立即关闭。

我们还使用ws 库测试了客户端,它提供了压缩示例,结果相同。我们尝试修改 ws 压缩选项,发现当我们评论 serverMaxWindowBits 选项(默认为协商值)时,可以建立连接并且发送和接收消息没有问题。我们也asked 控制uWebsockets 中的serverMaxWindowBits。

我们尝试的最后一件事是连接一个最小的 uWS 服务器和 websocket-sharp 客户端。 这是服务器的代码:

const uWS = require('uWebSockets.js');
const port = 5001;

const app = uWS.App({
    }).ws('/*', {
        /* Options */
        compression: 1, // Setting shared compression method
        maxPayloadLength: 4 * 1024,
        idleTimeout: 1000,
        /* Handlers */
        open: (ws, req) => {
            console.log('A WebSocket connected via URL: ' + req.getUrl() + '!');
        },
        message: (ws, message, isBinary) => {
            /* echo every message received */
            let ok = ws.send(message, isBinary);
        },
        drain: (ws) => {
            console.log('WebSocket backpressure: ' + ws.getBufferedAmount());
        },
        close: (ws, code, message) => {
            console.log('WebSocket closed');
        }
    }).any('/*', (res, req) => {
        res.end('Nothing to see here!');
    }).listen(port, (token) => {
        if (token) {
            console.log('Listening to port ' + port);
        } else {
            console.log('Failed to listen to port ' + port);
        }
    });

这是客户端代码:

using System;
using WebSocketSharp;

namespace Example
{
  public class Program
  {
    public static void Main (string[] args)
    {
      using (var ws = new WebSocket ("ws://localhost:5001")) {
        ws.OnMessage += (sender, e) =>
            Console.WriteLine ("server says: " + e.Data);

        ws.Compression = CompressionMethod.Deflate; // Turning on compression
        ws.Connect ();

        ws.Send ("{\"comm\":\"example\"}");
        Console.ReadKey (true);
      }
    }
  }
}

当我们运行服务器和客户端时,客户端发出以下错误:

错误|WebSocket.checkHandshakeResponse|服务器尚未发回“server_no_context_takeover”。 致命|WebSocket.doHandshake|包含无效的 Sec-WebSocket-Extensions 标头。

似乎客户端需要 server_no_context_takeover 标头,但没有收到。我们查看了 uWebsockets 源代码(uWebsockets.js 模块的 C++ 部分)并找到了一个 commented condition 用于发回 server_no_context_takeover 标头。于是我们取消了条件的注释,构建了uWebsockets.js,再次测试在客户端遇到如下错误:

WebSocketSharp.WebSocketException:无法从流中读取帧的标头。

有什么建议可以让这两个库一起工作吗?

【问题讨论】:

  • 不确定它是否有帮助,但 socket.io 默认会压缩。我知道Best HTTP 2 对 socket.io - websockets 有很好的支持。
  • @SamuelG 谢谢,但使用 socket.io 不是一个选项,因为我们目前正在以最少的资源处理 5k+ 并发连接。
  • @KooroshPasokhi 是什么得出了您认为 socket.io 无法处理您的负载或资源密集型的推理?希望了解更多关于您的测试的信息。
  • @SamuelG 评论不是用来讨论的,但是让我们说主要原因是socket.io的重点不是性能,我们不需要socket.io中更高层的抽象。

标签: node.js unity3d websocket websocket-sharp uwebsockets


【解决方案1】:

更新:根据我对uWebSockets.js 中代码的阅读,需要进行更改以启用所有参数websocket-sharp 需要设置以启用压缩。在高性能 Java 服务器 Vertx 中,以下设置适用于 Unity 兼容的websocket-sharp 进行压缩:

vertx.createHttpServer(new HttpServerOptions()
                .setMaxWebsocketFrameSize(65536)
                .setWebsocketAllowServerNoContext(true)
                .setWebsocketPreferredClientNoContext(true)
                .setMaxWebsocketMessageSize(100 * 65536)
                .setPerFrameWebsocketCompressionSupported(true)
                .setPerMessageWebsocketCompressionSupported(true)
                .setCompressionSupported(true));

以前:

错误是真的,websocket-sharp只支持permessage-deflate,改用DEDICATED_COMPRESSOR(compression: 2)。

【讨论】:

  • 不幸的是,将压缩方法设置为 2 并没有改变错误信息 :(
  • 那么 uWebSockets 存在一些潜在问题。我在客户端使用了带有 WebSocketSharp 压缩的 Java vertx websockets,它有更多的配置字段,并且可以正常工作。
  • 也许尝试直接在 uWebSockets.js 中编写一个测试来重现 WebSocket.cs 的标头拒绝行为? DEDICATED_COMPRESSOR 真的应该工作!
  • 你的意思是什么测试? uWebSockets.js 的架构有点复杂。它分为三层,分别用JS、C++和C编写,调试困难。
  • 我的意思是在 uWebSockets.js 项目目录中编写一个测试来重现握手 websocket-sharp 所做的事情,您可以通过将其连接到兼容的服务器并查看会发生什么来发现它?
猜你喜欢
  • 1970-01-01
  • 2015-10-26
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 1970-01-01
  • 2015-05-07
  • 2019-01-12
  • 1970-01-01
相关资源
最近更新 更多