ใช้การบีบอัด websocket กับ uWebSockets.js และ Websocket-Sharp


11

เรามีเกมมือถือที่ใช้ websocket สำหรับเชื่อมต่อ เซิร์ฟเวอร์เป็น app Node.js ใช้uWebSockets.jsห้องสมุดและลูกค้าเป็น app สามัคคีโดยใช้WebSocket ชาร์ปห้องสมุด พวกเขาเล่นได้ดีด้วยกันและเราไม่ได้พบปัญหากับพวกเขา

เมื่อเร็ว ๆ นี้เราต้องการที่จะช่วยให้การบีบอัด WebSocket ห้องสมุดทั้งสองระบุว่าพวกเขาสนับสนุนส่วนขยายการบีบอัดข้อความต่อข้อความ แต่ดูเหมือนว่ามีบางสิ่งที่เข้ากันไม่ได้ เพราะเมื่อเรากำหนดค่าให้ใช้การบีบอัดการเชื่อมต่อ websocket จะปิดลงทันทีในการจับมือกัน

นอกจากนี้เรายังทดสอบไคลเอ็นต์ด้วยไลบรารีwsและเป็นตัวอย่างสำหรับการบีบอัดด้วยผลลัพธ์เดียวกัน เราพยายามแก้ไขด้วยตัวเลือกการบีบอัด ws และพบว่าเมื่อเราแสดงความคิดเห็นตัวเลือก serverMaxWindowBits (ค่าเริ่มต้นของมูลค่าการเจรจาต่อรอง) การเชื่อมต่อสามารถสร้างและส่งและรับข้อความได้โดยไม่มีปัญหา นอกจากนี้เรายังถามเกี่ยวกับการควบคุม serverMaxWindowBits ใน uWebsockets

สิ่งสุดท้ายที่เราพยายามคือการเชื่อมต่อเซิร์ฟเวอร์ 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 (ส่วน 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 จะไม่สามารถจัดการกับภาระของคุณหรือเป็นทรัพยากรที่เข้มข้น? ชอบที่จะได้ยินเพิ่มเติมเกี่ยวกับการทดสอบของคุณ
ซามูเอลจี

@SamuelG ความคิดเห็นไม่ได้มีไว้สำหรับการอภิปราย แต่สมมติว่าเหตุผลหลักคือการเน้นของ socket.io ไม่ใช่ประสิทธิภาพและเราไม่ต้องการ abstractions ชั้นที่สูงขึ้นใน socket.io
Koorosh Pasokhi

คำตอบ:


3

อัปเดต:ตามการอ่านโค้ดของฉันการuWebSockets.jsเปลี่ยนแปลงจะต้องทำเพื่อให้พารามิเตอร์ทั้งหมดwebsocket-sharpจำเป็นต้องมีการตั้งค่าให้เปิดใช้งานการบีบอัด ใน Vertx เซิร์ฟเวอร์ Java ประสิทธิภาพสูงการตั้งค่าต่อไปนี้ใช้งานได้กับ Unity-compatible 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 ฉันใช้ websockets ของ Java ด้วยการบีบอัดด้วย WebSocketSharp ในไคลเอนต์ที่มีฟิลด์การกำหนดค่าเพิ่มเติมและใช้งานได้
DoctorPangloss

อาจลองสร้างการทดสอบโดยตรงใน uWebSockets.js ที่ทำให้เกิดพฤติกรรมของWebSocket.csการปฏิเสธส่วนหัวหรือไม่ DEDICATED_COMPRESSORควรทำงานจริง ๆ !
DoctorPangloss

คุณหมายถึงการทดสอบอะไร? สถาปัตยกรรมของ uWebSockets.js มีความซับซ้อนเล็กน้อย มันมีสามเลเยอร์เขียนใน JS, C ++ และ C ซึ่งทำให้การแก้จุดบกพร่องยาก
Koorosh Pasokhi

ฉันหมายถึงการเขียนการทดสอบในไดเรกทอรีโครงการ uWebSockets.js ที่ทำซ้ำ handshake websocket-sharp ซึ่งคุณสามารถค้นพบบางทีโดยการเชื่อมต่อกับเซิร์ฟเวอร์ที่เข้ากันได้และเห็นว่าเกิดอะไรขึ้น
DoctorPangloss
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.