在uWebSockets.js和Websocket-Sharp中使用websocket压缩


11

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

最近,我们想启用websocket压缩。这两个库都声明它们支持按消息压缩扩展,但是似乎有些东西与它们不兼容。因为当我们配置为使用压缩时,Websocket连接在握手时立即关闭。

我们还使用ws库测试了客户端,并提供了具有相同结果的压缩示例。我们尝试修改ws压缩选项,发现在注释serverMaxWindowBits选项(默认为协商值)时,可以建立连接,发送和接收消息也可以正常工作。我们还询问了如何在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”。Fatal | WebSocket.doHandshake |包含无效的Sec-WebSocket-Extensions标头。

客户端似乎期望server_no_context_takeover标头,但没有收到。我们检查了uWebsockets源代码(uWebsockets.js模块的C ++部分),发现了发送回server_no_context_takeover标头的注释条件。因此,我们取消了注释条件,并构建了uWebsockets.js并再次进行测试以在客户端中遇到以下错误:

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

有什么建议可以使这两个库协同工作?


不确定它是否有帮助,但默认情况下socket.io确实会压缩。我知道Best HTTP 2对socket.io-websockets有很好的支持。
塞缪尔G

@SamuelG谢谢,但是不能选择使用socket.io,因为我们目前正在以最少的资源处理5k +并发连接。
Koorosh Pasokhi

@KooroshPasokhi是什么原因说明您得出这样的结论,即socket.io无法处理您的负载或资源密集型?很想听到更多关于您的测试的信息。
塞缪尔G

@SamuelG评论不是用于讨论,而是说主要原因是socket.io的重点不是性能,我们不需要socket.io中的更高层抽象。
Koorosh Pasokhi

Answers:


3

更新:根据我对中代码的阅读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_COMPRESSORcompression: 2)来代替。


不幸的是,将压缩方法设置为2并没有改变错误消息:(
Koorosh Pasokhi

然后uWebSockets有一些潜在的问题。我在客户端中使用Java的vertx websockets和WebSocketSharp进行压缩,该客户端具有更多配置字段,并且可以正常工作。
DoctorPangloss

也许尝试直接在uWebSockets.js中编写可重现WebSocket.cs头拒绝行为的测试?DEDICATED_COMPRESSOR真的应该工作!
DoctorPangloss

你是什​​么意思 uWebSockets.js的体系结构有些复杂。它具有用JS,C ++和C编写的三层,这使得调试变得很困难。
Koorosh Pasokhi,

我的意思是在uWebSockets.js项目目录中编写一个可再现websocket-sharp握手的测试,您可以通过将其连接到兼容服务器并查看会发生什么来发现这一点?
DoctorPangloss
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.