NativeWebSocket

repository·master·Indexed 23 days ago

https://github.com/endel/nativewebsocket

A lightweight, dependency-free WebSocket client library for cross-platform .NET development. It specifically targets game engines such as Unity (2019.1+), MonoGame, and Godot, as well as generic .NET environments. The library provides an asynchronous API for connecting, sending binary or text data, and handling events like OnOpen, OnMessage, OnError, and OnClose.

Tokens
4.5K
Snippets
9
Records
21
Agent score
83%

What's inside NativeWebSocket

  1. Overview of Native WebSocket Client

    master
    Native WebSocket Client is a lightweight WebSocket library designed for ease of use in Unity and other .NET environments. It requires no external DLLs and supports all major build targets, including WebGL/HTML5. The core functionality is provided by the NativeWebSocket.WebSocket class.
  2. What is measured in NativeWebSocket benchmarks

    master

    The benchmarks measure several key performance indicators across different payload sizes (32B, 256B, 1KB, 8KB, 64KB):

    BenchmarkDescriptionKey Metrics
    LatencyRound-trip time (send → echo → receive)min/avg/median/p95/p99/max/stddev (ms)
    Throughput_SendMessages sent per secondmsgs/sec, MB/sec
    Throughput_RecvMessages received per second (server floods)msgs/sec, MB/sec
    Throughput_BidirSimultaneous send + receivesend & recv msgs/sec
    GCAlloc_SendHeap allocation per Send() callbytes/op, GC collections
    GCAlloc_DispatchHeap allocation per DispatchMessageQueue()bytes/op, GC collections
    FrameTime_BaselineDispatch overhead with no trafficavg/p99/max/jitter (ms)
    FrameTime_DispatchDispatch overhead under 50k-message floodavg/median/p95/p99/max/jitter (ms)
    FrameTime_UnderLoadTotal frame time during floodavg/p99/max/jitter (ms)
    BurstProcess 100 messages sent in <10mstotal time, peak/frame, peak frame time

    Note: The Unity BenchmarkRunner can selectively enable specific runs via runThroughputSend, runThroughputReceive, or runThroughputBidirectional.

  3. Start the NativeWebSocket benchmark server

    master

    The benchmark server is a Node.js application that acts as a WebSocket echo and flood server. It listens on ws://localhost:3000 by default. You can change the port by setting the PORT environment variable.

    To start the server:

    1. Navigate to the server directory.
    2. Install dependencies.
    3. Run the server.
    cd benchmarks/server
    npm install
    node index.js
  4. Install NativeWebSocket in Unity

    master

    NativeWebSocket requires Unity 2019.1+ with .NET 4.x+ Runtime.

    Important: Do not copy raw source files directly into your project, as the core WebSocket.cs requires build-time transformations for WebGL support. Use one of the following methods:

    Via UPM (Unity Package Manager)

    1. Open Unity and the Package Manager Window.
    2. Click Add Package From Git URL.
    3. Enter: https://github.com/endel/NativeWebSocket.git#upm-2

    Note: For the legacy 1.x version, use https://github.com/endel/NativeWebSocket.git#upm.

    Via .unitypackage

    1. Download NativeWebSocket.unitypackage from the Releases page.
    2. In Unity, go to Assets > Import Package > Custom Package and select the file.
    https://github.com/endel/NativeWebSocket.git#upm-2
  5. Install NativeWebSocket in MonoGame or Godot

    master

    Use the .NET CLI to add the necessary packages:

    For MonoGame:

    dotnet add package Colyseus.NativeWebSocket
    dotnet add package Colyseus.NativeWebSocket.MonoGame

    For Godot (C#):

    dotnet add package Colyseus.NativeWebSocket
    dotnet add package Colyseus.NativeWebSocket
    dotnet add package Colyseus.NativeWebSocket.MonoGame
  6. Migrate from NativeWebSocket 1.x to 2.x

    master

    The 2.x version introduces several breaking changes aimed at making the library a universal .NET library.

    Key Changes

    • Universal .NET: The core library no longer depends on UnityEngine. It targets netstandard2.0 and net6.0.
    • Automatic Event Dispatching: MainThreadUtil, WaitForUpdate, and WaitForBackgroundThread have been removed. Events are now automatically dispatched via SynchronizationContext in Unity, Godot, and MonoGame. Remove any manual DispatchMessageQueue() calls from your Update() loops in these engines.
    • Close() Signature: Close() now accepts an optional WebSocketCloseCode and string reason. Existing calls without arguments still work.
    • IWebSocket Interface: If you implement this interface, you must now include the new methods: Connect(), Close(...), Send(...), and SendText(...).
    • Installation: You can no longer copy raw source files into Unity; use UPM or .unitypackage to ensure WebGL compatibility.

    Migration Checklist

    What changedAction required
    MainThreadUtil / WaitForUpdate / WaitForBackgroundThread removedDelete any code using these classes
    Automatic event dispatchingRemove DispatchMessageQueue() from Update() (Unity/Godot/MonoGame)
    Custom IWebSocket implementationsAdd Connect(), Close(), Send(), SendText() methods
    Manual file copy installsSwitch to UPM or .unitypackage
  7. Run BenchmarkNew (universal implementation) in Unity

    master

    To test the new universal implementation:

    1. Create a new Unity project (version 2019.4+).
    2. Copy the contents of BenchmarkNew/Assets/ into your project's Assets/ folder.
    3. Create an empty scene and add an empty GameObject with the BenchmarkRunner component.
    4. In the Inspector, ensure implementationName is set to "new".
    5. Press Play.
  8. Run BenchmarkOld (master implementation) in Unity

    master

    To test the legacy implementation:

    1. Create a new Unity project (version 2019.4+).
    2. Copy the contents of BenchmarkOld/Assets/ into your project's Assets/ folder.
    3. Create an empty scene and add an empty GameObject with the BenchmarkRunner component.
    4. In the Inspector, ensure implementationName is set to "old".
    5. Press Play.
  9. Aggregate and compare benchmark CSV results

    master

    Use the provided Python script to aggregate multiple CSV runs and compare the performance of the old baseline against the new candidate implementation.

    Available Filters:

    • --benchmarks: Filter by benchmark name (e.g., Throughput_Recv, FrameTime_Dispatch, Burst).
    • --metrics: Filter by specific metrics (e.g., msgs_per_sec, avg_ms, p95_ms, p99_ms, total_time_ms).
    • --payloads: Filter by payload sizes (e.g., 32 256 1024).
    python3 benchmarks/compare_results.py \
      /path/to/benchmark_old_sync.csv \
      /path/to/benchmark_old_sync_2.csv \
      /path/to/benchmark_new_sync.csv \
      /path/to/benchmark_new_sync_2.csv \
      --baseline old \
      --candidate new
  10. Run Unity sync-context benchmarks in batchmode

    master

    You can run targeted Unity benchmarks (receive throughput, frame time, and burst tests) using the BenchmarkBatchRunner.RunSyncContextBenchmarks asset. This runs in Unity batchmode, writes results to a CSV, and exits.

    Use the following command-line arguments to configure the run:

    • -benchmarkImplementation <old|new>: Select the implementation to test.
    • -benchmarkOutput <path>: Specify the output CSV file path.
    • -benchmarkThroughputDuration <seconds>: Duration of the throughput test.
    • -benchmarkPayloadSizes <comma_separated_sizes>: e.g., 32,256,1024,8192,65536.
  11. Use NativeWebSocket in Generic .NET (Console/No SynchronizationContext)

    master

    In environments without a SynchronizationContext (like a standard Console application), you must manually call DispatchMessageQueue() from your main loop to process queued events.

    var ws = new WebSocket("ws://localhost:3000");
    ws.OnMessage += (bytes) => Console.WriteLine("Received " + bytes.Length + " bytes");
    _ = ws.Connect();
    
    while (true)
    {
        ws.DispatchMessageQueue();
        Thread.Sleep(16);
    }