Використання стиснення websocket за допомогою uWebSockets.js та Websocket-Sharp


11

У нас є мобільна гра, яка використовує websocket для з'єднань. Сервер - це додаток Node.js, що використовує бібліотеку uWebSockets.js, а клієнт - додаток Unity, що використовує бібліотеку Websocket-Sharp . Вони обоє добре грають разом, і ми не стикалися з ними.

Нещодавно ми хотіли включити стиснення websocket . Обидві бібліотеки заявили, що вони підтримують розширення стиснення за повідомленнями, але, здається, є щось несумісне з ними. Тому що, коли ми налаштовуємо на стиснення, підключення веб-розетки негайно закривається при рукостисканні.

Ми також протестували клієнта з бібліотекою ws, і це приклад для стиснення з тим же результатом. Ми спробували познайомитися з параметрами стиснення ws і виявили, що коли ми коментуємо параметр serverMaxWindowBits (за замовчуванням до узгодженого значення), з'єднання може бути встановлено, а відправка та отримання повідомлень працює без проблем. Ми також запитали про управління серверомMaxWindowBits в uWebsockets.

Останнє, що ми спробували, - це підключення мінімального сервера uWS та клієнта, гострого веб-сокета. Ось код для сервера:

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 (C ++ частина модуля uWebsockets.js) і виявили коментовану умову для надсилання назад заголовка server_no_context_takeover. Тож ми прокоментували умову та створили uWebsockets.js і знову протестували, щоб зіткнутися з такою помилкою в клієнті:

WebSocketSharp.WebSocketException: Заголовок кадру не може бути прочитаний з потоку.

Будь-які пропозиції щодо того, щоб ці дві бібліотеки працювали разом?


Не впевнений, що це взагалі допомагає, але socket.io стискає за замовчуванням. Я знаю, що найкращий HTTP 2 має досить гарну підтримку socket.io - websockets.
Самуель Г

@SamuelG Дякую, але використання socket.io - це не варіант, оскільки ми зараз обробляємо 5k + одночасні з'єднання з мінімальними ресурсами.
Koorosh Pasokhi

@KooroshPasokhi, що зробив ваше висновок про те, що socket.io не зможе впоратися з вашим навантаженням або потребує ресурсів? Хочеться почути більше про ваші тести.
Самуель G

@SamuelG Коментарі не для обговорення, але скажімо, що основними причинами є фокус роботи socket.io - не ефективність, і нам не потрібні абстракції вищого рівня в socket.io.
Koorosh Pasokhi

Відповіді:


3

Оновлення: На підставі мого читання коду в uWebSockets.js, потрібно було б внести зміни, щоб включити всі параметри, websocket-sharpнеобхідні для включення стиснення. У Vertx, високоефективному сервері Java, наступні налаштування працюють з 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 не змінило повідомлення про помилку :(
Koorosh Pasokhi

Тоді виникає деяка основна проблема з uWebSockets. Я використовую вертексні вершини Java з компресією за допомогою WebSocketSharp у клієнта, який має більше конфігураційних полів, і він просто працює.
Доктор Панглос

Можливо, спробуйте створити тест безпосередньо в uWebSockets.js, який відтворює поведінку WebSocket.csвідхилення заголовка? DEDICATED_COMPRESSORдійсно має працювати!
Доктор Панглос

Який тест ви маєте на увазі? Архітектура uWebSockets.js трохи складна. Він має три шари, написані на JS, C ++ та C, що робить налагодження важким.
Корош Пасохі

Я маю на увазі створення тесту в каталозі проектів uWebSockets.js, який відтворює чіткі веб-сокети рукостискання, які ви можете виявити, можливо, підключивши його до сумісного сервера і побачивши, що відбувається?
DoctorPangloss
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.