Sử dụng nén websocket với uWebSockets.js và Websocket-Sharp


11

Chúng tôi có một trò chơi di động sử dụng websocket cho các kết nối. Máy chủ là ứng dụng Node.js sử dụng thư viện uWebSockets.js và máy khách là ứng dụng Unity sử dụng Websocket-Sharp thư viện . Cả hai chơi tốt với nhau và chúng tôi đã không gặp phải vấn đề gì với họ.

Gần đây, chúng tôi muốn kích hoạt tính năng nén websocket . Cả hai thư viện đều tuyên bố rằng họ hỗ trợ tiện ích mở rộng Nén tin nhắn nhưng có vẻ như có gì đó không tương thích với họ. Bởi vì khi chúng tôi định cấu hình để sử dụng nén, kết nối websocket sẽ đóng ngay lập tức khi bắt tay.

Chúng tôi cũng đã thử nghiệm ứng dụng khách với thư viện ws và nó cung cấp ví dụ để nén với kết quả tương tự. Chúng tôi đã thử mày mò các tùy chọn nén ws và thấy rằng khi chúng tôi nhận xét tùy chọn serverMaxWindowBits (mặc định là giá trị thương lượng), kết nối có thể được thiết lập và gửi và nhận tin nhắn hoạt động mà không gặp sự cố. Chúng tôi cũng đã hỏi về việc kiểm soát serverMaxWindowBits trong uWebsockets.

Điều cuối cùng chúng tôi đã thử là kết nối một máy chủ uWS tối thiểu và máy khách sắc nét websocket. Đây là mã cho máy chủ:

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);
        }
    });

Đây là mã khách hàng:

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);
      }
    }
  }
}

Khi chúng tôi chạy máy chủ và máy khách, máy khách sẽ phát ra lỗi sau:

Lỗi | WebSocket.checkHandshakeResponse | Máy chủ chưa gửi lại 'server_no_context_takeover'. Fatal | WebSocket.doHandshake | Bao gồm tiêu đề Sec-WebSocket-Tiện ích mở rộng không hợp lệ.

Có vẻ như khách hàng mong đợi tiêu đề server_no_context_takeover và không nhận được tiêu đề. Chúng tôi đã xem xét nguồn uWebsockets (một phần C ++ của mô-đun uWebsockets.js) và tìm thấy một điều kiện nhận xét để gửi lại tiêu đề server_no_context_takeover. Vì vậy, chúng tôi đã bỏ qua điều kiện và xây dựng uWebsockets.js và thử nghiệm lại để gặp lỗi sau trong máy khách:

WebSocketSharp.WebSocketException: Không thể đọc tiêu đề của khung từ luồng.

Bất kỳ đề xuất để làm cho hai thư viện này làm việc cùng nhau?


Không chắc chắn nó có giúp ích gì không, nhưng socket.io không nén theo mặc định. Tôi biết Best HTTP 2 có hỗ trợ khá tốt cho socket.io - websockets.
Samuel G

@SamuelG Cảm ơn, nhưng sử dụng socket.io không phải là một tùy chọn vì chúng tôi hiện đang xử lý 5k + kết nối đồng thời với tài nguyên tối thiểu.
Koorosh Pasokhi

@KooroshPasokhi điều gì đã kết luận lý do của bạn rằng socket.io sẽ không thể xử lý tải của bạn hoặc tốn nhiều tài nguyên? Rất thích nghe thêm về các bài kiểm tra của bạn.
Samuel G

@SamuelG Nhận xét không dành cho các cuộc thảo luận, nhưng giả sử các lý do chính là trọng tâm của socket.io không phải là hiệu suất và chúng tôi không cần trừu tượng lớp cao hơn trong socket.io.
Koorosh Pasokhi

Câu trả lời:


3

Cập nhật: Dựa trên việc tôi đọc mã trong uWebSockets.js, các thay đổi sẽ cần được thực hiện để cho phép tất cả các tham số websocket-sharpcần đặt để bật nén. Trong Vertx, máy chủ Java hiệu suất cao, các cài đặt sau hoạt động với tính tương thích Unity websocket-sharpđể nén:

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

Trước đây:

Lỗi là có thật, websocket-sharpchỉ hỗ trợ permessage-deflate, sử dụng DEDICATED_COMPRESSOR( compression: 2) thay thế.


Thật không may, cài đặt phương thức nén thành 2 đã không thay đổi thông báo lỗi :(
Koorosh Pasokhi

Sau đó, có một số vấn đề cơ bản với uWebSockets. Tôi sử dụng các webs vertx của Java để nén với WebSocketSharp trong máy khách có nhiều trường cấu hình hơn và nó chỉ hoạt động.
DoctorPangloss

Có thể thử tác giả một bài kiểm tra trực tiếp trong uWebSockets.js để tái tạo hành vi WebSocket.cstừ chối tiêu đề? DEDICATED_COMPRESSORthực sự nên làm việc
DoctorPangloss

Bạn có ý nghĩa gì trong bài kiểm tra? Kiến trúc của uWebSockets.js hơi phức tạp. Nó có ba lớp được viết bằng JS, C ++ và C, khiến việc gỡ lỗi trở nên khó khăn.
Koorosh Pasokhi

Ý tôi là tác giả một bài kiểm tra trong thư mục dự án uWebSockets.js tái tạo websocket bắt tay, điều mà bạn có thể khám phá có thể bằng cách kết nối nó với một máy chủ tuân thủ và xem điều gì xảy ra?
DoctorPangloss
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.