Ecng.Net.SocketIO 1.0.527

There is a newer version of this package available.
See the version list below for details.
dotnet add package Ecng.Net.SocketIO --version 1.0.527
                    
NuGet\Install-Package Ecng.Net.SocketIO -Version 1.0.527
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Ecng.Net.SocketIO" Version="1.0.527" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Ecng.Net.SocketIO" Version="1.0.527" />
                    
Directory.Packages.props
<PackageReference Include="Ecng.Net.SocketIO" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Ecng.Net.SocketIO --version 1.0.527
                    
#r "nuget: Ecng.Net.SocketIO, 1.0.527"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Ecng.Net.SocketIO@1.0.527
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Ecng.Net.SocketIO&version=1.0.527
                    
Install as a Cake Addin
#tool nuget:?package=Ecng.Net.SocketIO&version=1.0.527
                    
Install as a Cake Tool

Ecng.Net.SocketIO

A high-performance .NET client library for WebSocket communication with automatic reconnection, message resending, and comprehensive connection state management.

Features

  • WebSocket Client Implementation - Full-featured WebSocket client with async/await support
  • Automatic Reconnection - Configurable reconnection attempts with exponential backoff
  • Command Resending - Automatic resend of commands after reconnection
  • Connection State Tracking - Track and aggregate connection states across multiple connections
  • JSON Serialization - Built-in JSON serialization for object messages
  • Flexible Logging - Customizable logging hooks for info, error, and verbose messages
  • RestSharp Integration - Helper methods for REST API calls with authentication
  • Thread-Safe - Safe to use in multi-threaded environments

Installation

Add the package reference to your project:

<PackageReference Include="Ecng.Net.SocketIO" Version="x.x.x" />

Quick Start

Basic WebSocket Connection

using Ecng.Net;

var socket = new WebSocketClient(
    url: "wss://example.com/socket",
    stateChanged: state => Console.WriteLine($"State: {state}"),
    error: ex => Console.WriteLine($"Error: {ex.Message}"),
    process: (msg, ct) =>
    {
        Console.WriteLine($"Received: {msg.AsString()}");
        return ValueTask.CompletedTask;
    },
    infoLog: (fmt, args) => Console.WriteLine(fmt, args),
    errorLog: (fmt, args) => Console.Error.WriteLine(fmt, args),
    verboseLog: (fmt, args) => Console.WriteLine($"[VERBOSE] {fmt}", args)
);

await socket.ConnectAsync(CancellationToken.None);

Sending Messages

// Send JSON object
await socket.SendAsync(new { type = "subscribe", channel = "trades" });

// Send string
await socket.SendAsync("Hello, WebSocket!");

// Send raw bytes
byte[] data = Encoding.UTF8.GetBytes("Raw message");
await socket.SendAsync(data, WebSocketMessageType.Text);

Core Components

WebSocketClient

The main class for WebSocket communication.

Constructor Parameters
public WebSocketClient(
    string url,                              // WebSocket URL (ws:// or wss://)
    Action<ConnectionStates> stateChanged,   // Connection state change callback
    Action<Exception> error,                 // Error handler
    Func<WebSocketMessage, CancellationToken, ValueTask> process,  // Message processor
    Action<string, object> infoLog,          // Info log handler
    Action<string, object> errorLog,         // Error log handler
    Action<string, object> verboseLog        // Verbose log handler (can be null)
)
Configuration Properties
// Reconnection settings
socket.ReconnectAttempts = 10;              // -1 for infinite, 0 for no reconnect
socket.ReconnectInterval = TimeSpan.FromSeconds(5);
socket.ResendInterval = TimeSpan.FromSeconds(2);
socket.ResendTimeout = TimeSpan.FromMilliseconds(500);

// Message encoding
socket.Encoding = Encoding.UTF8;

// Buffer sizes
socket.BufferSize = 1024 * 1024;            // 1MB for compressed data
socket.BufferSizeUncompress = 10 * 1024 * 1024; // 10MB for uncompressed

// JSON serialization
socket.Indent = true;
socket.SendSettings = new JsonSerializerSettings { ... };

// Auto-resend control
socket.DisableAutoResend = false;
Connection Management
// Connect
await socket.ConnectAsync(cancellationToken);
socket.Connect(); // Synchronous version

// Disconnect
socket.Disconnect();

// Check connection state
bool isConnected = socket.IsConnected;
ConnectionStates currentState = socket.State;

// Abort connection immediately
socket.Abort();
Sending Messages with Subscription Tracking
// Send with subscription ID for automatic resend after reconnect
long subscriptionId = 12345;
await socket.SendAsync(
    obj: new { action = "subscribe", symbol = "BTCUSD" },
    subId: subscriptionId
);

// Unsubscribe (negative ID removes from resend queue)
await socket.SendAsync(
    obj: new { action = "unsubscribe", symbol = "BTCUSD" },
    subId: -subscriptionId
);

// Manual resend management
socket.RemoveResend(subscriptionId);  // Remove specific subscription
socket.RemoveResend();                 // Remove all subscriptions
Advanced Features
// Custom initialization
socket.Init += ws =>
{
    ws.Options.SetRequestHeader("X-Custom-Header", "value");
    ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(30);
};

// Post-connect hook
socket.PostConnect += async (isReconnect, ct) =>
{
    if (isReconnect)
        Console.WriteLine("Reconnected! Resubscribing...");

    await Task.CompletedTask;
};

// Pre-process received data (e.g., decompression)
socket.PreProcess2 = (input, output) =>
{
    // Decompress or transform data
    input.CopyTo(output);
    return input.Length;
};

// Send ping frame
await socket.SendOpCode(0x9);

WebSocketMessage

Represents an incoming message from the WebSocket.

// In your message processor
Func<WebSocketMessage, CancellationToken, ValueTask> process = (msg, ct) =>
{
    // Get as string
    string text = msg.AsString();

    // Deserialize to object
    var trade = msg.AsObject<TradeData>();

    // Deserialize to dynamic
    dynamic data = msg.AsObject();

    // Get JSON reader for streaming
    using var reader = msg.AsReader();

    // Access raw bytes
    ReadOnlyMemory<byte> bytes = msg.Memory;

    return ValueTask.CompletedTask;
};

Connection States

The ConnectionStates enum represents the current state of the connection:

public enum ConnectionStates
{
    Disconnected,   // Not connected
    Disconnecting,  // In process of disconnecting
    Connecting,     // In process of connecting
    Connected,      // Successfully connected
    Reconnecting,   // Attempting to reconnect
    Restored,       // Connection restored after reconnect
    Failed          // Connection failed
}

ConnectionStateTracker

Track and aggregate states across multiple connections.

var tracker = new ConnectionStateTracker();

// Add connections
tracker.Add(socket1);
tracker.Add(socket2);

// Monitor overall state
tracker.StateChanged += state =>
    Console.WriteLine($"Overall state: {state}");

// Connect all
await tracker.ConnectAsync(CancellationToken.None);

// Disconnect all
tracker.Disconnect();

// Remove connections
tracker.Remove(socket1);

The tracker aggregates states with the following logic:

  • Connected: All connections are connected
  • Reconnecting: Any connection is reconnecting
  • Restored: All connections are connected or restored
  • Failed: All connections have failed
  • Disconnected: All connections are disconnected or failed

IConnection Interface

Standard interface for connection management:

public interface IConnection
{
    event Action<ConnectionStates> StateChanged;
    ValueTask ConnectAsync(CancellationToken cancellationToken);
    void Disconnect();
}

Both WebSocketClient and ConnectionStateTracker implement this interface.

RestSharp Integration

The library includes helper methods for REST API calls, often used alongside WebSocket connections.

Basic REST Request

using Ecng.Net;
using RestSharp;

var request = new RestRequest(Method.Get);
request.AddQueryParameter("symbol", "BTCUSD");

var response = await request.InvokeAsync<PriceData>(
    url: new Uri("https://api.example.com/price"),
    caller: this,
    logVerbose: (fmt, args) => Console.WriteLine(fmt, args),
    token: CancellationToken.None
);

Console.WriteLine($"Price: {response.Price}");

Authentication

// Bearer token authentication
request.SetBearer(secureToken);

// Custom authenticator
var authenticator = new MyCustomAuthenticator();
var response = await request.InvokeAsync2<Data>(
    url: apiUrl,
    caller: this,
    logVerbose: logger,
    token: cancellationToken,
    auth: authenticator
);

Error Handling

try
{
    var response = await request.InvokeAsync<Data>(url, this, logger, token);
}
catch (RestSharpException ex)
{
    Console.WriteLine($"HTTP {ex.Response.StatusCode}: {ex.Response.Content}");
    Console.WriteLine($"Error: {ex.Message}");
}

Advanced REST Features

// Custom content converter
var response = await request.InvokeAsync<Data>(
    url: apiUrl,
    caller: this,
    logVerbose: logger,
    token: cancellationToken,
    contentConverter: content => content.Replace("null", "\"\"")
);

// Handle specific error status codes
var response = await request.InvokeAsync3<Data>(
    url: apiUrl,
    caller: this,
    logVerbose: logger,
    token: cancellationToken,
    handleErrorStatus: statusCode =>
    {
        if (statusCode == HttpStatusCode.TooManyRequests)
        {
            // Custom handling
            return true; // Handled
        }
        return false; // Not handled, will throw
    }
);

// Add body as string
request.AddBodyAsStr("{\"key\": \"value\"}");

// Remove parameters
request.RemoveWhere(p => p.Name == "old_param");

// Convert parameters to query string
string queryString = request.Parameters.ToQueryString();

JWT Decoding

string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
var parts = token.DecodeJWT();

foreach (var part in parts)
{
    Console.WriteLine(part);
}

Complete Examples

Crypto Exchange WebSocket Client

public class CryptoExchangeClient : IDisposable
{
    private readonly WebSocketClient _socket;
    private long _subscriptionCounter;

    public CryptoExchangeClient(string wsUrl)
    {
        _socket = new WebSocketClient(
            url: wsUrl,
            stateChanged: OnStateChanged,
            error: OnError,
            process: ProcessMessage,
            infoLog: (fmt, args) => Console.WriteLine($"[INFO] {fmt}", args),
            errorLog: (fmt, args) => Console.Error.WriteLine($"[ERROR] {fmt}", args),
            verboseLog: null
        )
        {
            ReconnectAttempts = -1,  // Infinite reconnection
            ReconnectInterval = TimeSpan.FromSeconds(5),
            ResendTimeout = TimeSpan.FromSeconds(1)
        };

        _socket.Init += ws =>
        {
            ws.Options.KeepAliveInterval = TimeSpan.FromSeconds(20);
        };

        _socket.PostConnect += async (isReconnect, ct) =>
        {
            if (isReconnect)
            {
                Console.WriteLine("Reconnected! Subscriptions will be restored automatically.");
            }
        };
    }

    public async Task ConnectAsync()
    {
        await _socket.ConnectAsync(CancellationToken.None);
    }

    public async Task SubscribeToTradesAsync(string symbol)
    {
        var subId = ++_subscriptionCounter;

        await _socket.SendAsync(
            obj: new
            {
                type = "subscribe",
                channel = "trades",
                symbol = symbol
            },
            subId: subId
        );

        Console.WriteLine($"Subscribed to {symbol} trades (ID: {subId})");
    }

    public async Task UnsubscribeFromTradesAsync(long subscriptionId, string symbol)
    {
        await _socket.SendAsync(
            obj: new
            {
                type = "unsubscribe",
                channel = "trades",
                symbol = symbol
            },
            subId: -subscriptionId  // Negative to remove from resend queue
        );
    }

    private void OnStateChanged(ConnectionStates state)
    {
        Console.WriteLine($"Connection state: {state}");

        if (state == ConnectionStates.Connected)
        {
            // Connection established
        }
        else if (state == ConnectionStates.Restored)
        {
            // Connection restored after disconnect
        }
        else if (state == ConnectionStates.Failed)
        {
            // Connection failed after all retry attempts
        }
    }

    private void OnError(Exception ex)
    {
        Console.Error.WriteLine($"WebSocket error: {ex}");
    }

    private async ValueTask ProcessMessage(WebSocketMessage msg, CancellationToken ct)
    {
        try
        {
            var message = msg.AsObject<dynamic>();

            if (message.type == "trade")
            {
                Console.WriteLine($"Trade: {message.symbol} @ {message.price}");
            }
            else if (message.type == "error")
            {
                Console.Error.WriteLine($"Server error: {message.message}");
            }
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine($"Error processing message: {ex.Message}");
        }

        await ValueTask.CompletedTask;
    }

    public void Dispose()
    {
        _socket?.Disconnect();
        _socket?.Dispose();
    }
}

// Usage
await using var client = new CryptoExchangeClient("wss://api.exchange.com/ws");
await client.ConnectAsync();
await client.SubscribeToTradesAsync("BTCUSD");

// Keep running
await Task.Delay(Timeout.Infinite);

Multi-Connection Manager

public class MultiExchangeClient
{
    private readonly ConnectionStateTracker _tracker;
    private readonly WebSocketClient _exchangeA;
    private readonly WebSocketClient _exchangeB;

    public MultiExchangeClient()
    {
        _tracker = new ConnectionStateTracker();

        _exchangeA = CreateClient("wss://exchange-a.com/ws", "Exchange A");
        _exchangeB = CreateClient("wss://exchange-b.com/ws", "Exchange B");

        _tracker.Add(_exchangeA);
        _tracker.Add(_exchangeB);

        _tracker.StateChanged += state =>
        {
            Console.WriteLine($"Overall connection state: {state}");

            if (state == ConnectionStates.Connected)
            {
                Console.WriteLine("All exchanges connected!");
            }
        };
    }

    private WebSocketClient CreateClient(string url, string name)
    {
        return new WebSocketClient(
            url: url,
            stateChanged: state => Console.WriteLine($"{name}: {state}"),
            error: ex => Console.Error.WriteLine($"{name} error: {ex.Message}"),
            process: (msg, ct) =>
            {
                Console.WriteLine($"{name}: {msg.AsString()}");
                return ValueTask.CompletedTask;
            },
            infoLog: (fmt, args) => Console.WriteLine($"[{name}] {fmt}", args),
            errorLog: (fmt, args) => Console.Error.WriteLine($"[{name}] {fmt}", args),
            verboseLog: null
        )
        {
            ReconnectAttempts = 5,
            ReconnectInterval = TimeSpan.FromSeconds(3)
        };
    }

    public async Task ConnectAllAsync()
    {
        await _tracker.ConnectAsync(CancellationToken.None);
    }

    public void DisconnectAll()
    {
        _tracker.Disconnect();
    }
}

WebSocket with REST API Integration

public class TradingClient
{
    private readonly WebSocketClient _wsClient;
    private readonly Uri _restApiUrl;

    public TradingClient(string wsUrl, string restUrl)
    {
        _restApiUrl = new Uri(restUrl);
        _wsClient = new WebSocketClient(
            url: wsUrl,
            stateChanged: state => Console.WriteLine($"WS State: {state}"),
            error: ex => Console.Error.WriteLine($"WS Error: {ex}"),
            process: ProcessWebSocketMessage,
            infoLog: (fmt, args) => Console.WriteLine(fmt, args),
            errorLog: (fmt, args) => Console.Error.WriteLine(fmt, args),
            verboseLog: null
        );
    }

    public async Task<AccountInfo> GetAccountInfoAsync()
    {
        var request = new RestRequest("/account", Method.Get);
        request.SetBearer(GetAuthToken());

        try
        {
            var account = await request.InvokeAsync<AccountInfo>(
                url: new Uri(_restApiUrl, request.Resource),
                caller: this,
                logVerbose: (fmt, args) => Console.WriteLine(fmt, args),
                token: CancellationToken.None
            );

            return account;
        }
        catch (RestSharpException ex)
        {
            Console.Error.WriteLine($"REST API Error: {ex.Message}");
            Console.Error.WriteLine($"Status: {ex.Response.StatusCode}");
            Console.Error.WriteLine($"Content: {ex.Response.Content}");
            throw;
        }
    }

    public async Task PlaceOrderAsync(string symbol, decimal price, decimal quantity)
    {
        var request = new RestRequest("/orders", Method.Post);
        request.SetBearer(GetAuthToken());
        request.AddBodyAsStr(new
        {
            symbol = symbol,
            price = price,
            quantity = quantity
        }.ToJson());

        var order = await request.InvokeAsync<Order>(
            url: new Uri(_restApiUrl, request.Resource),
            caller: this,
            logVerbose: (fmt, args) => Console.WriteLine(fmt, args),
            token: CancellationToken.None
        );

        Console.WriteLine($"Order placed: {order.Id}");
    }

    private async ValueTask ProcessWebSocketMessage(WebSocketMessage msg, CancellationToken ct)
    {
        var data = msg.AsObject<dynamic>();

        if (data.type == "order_update")
        {
            Console.WriteLine($"Order {data.orderId} status: {data.status}");
        }

        await ValueTask.CompletedTask;
    }

    private SecureString GetAuthToken()
    {
        // Return your authentication token
        throw new NotImplementedException();
    }
}

Best Practices

  1. Always handle errors: Provide error handlers to catch and log exceptions.

  2. Configure reconnection: Set appropriate reconnection attempts and intervals based on your use case.

  3. Use subscription IDs: Track subscriptions with IDs for automatic resend after reconnection.

  4. Monitor connection states: React to state changes to update your UI or trigger business logic.

  5. Dispose properly: Always dispose of WebSocketClient when done to clean up resources.

  6. Use async/await: Prefer async methods for better scalability.

  7. Implement backoff: Use increasing reconnection intervals to avoid overwhelming the server.

  8. Log appropriately: Use different log levels (info, error, verbose) for debugging and monitoring.

Thread Safety

The WebSocketClient class is designed to be thread-safe for the following operations:

  • Sending messages
  • Connection/disconnection
  • State management
  • Subscription tracking

However, you should not share a single WebSocketMessage instance across threads, as it contains read-only memory references.

Performance Considerations

  • Buffer Sizes: Adjust BufferSize and BufferSizeUncompress based on your message sizes.
  • Resend Interval: Lower intervals increase network traffic; higher intervals delay recovery.
  • Reconnect Attempts: Balance between reliability and resource usage.
  • Verbose Logging: Disable in production for better performance.

License

This library is part of the Ecng framework.

Support

For issues, questions, or contributions, please refer to the main StockSharp repository.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on Ecng.Net.SocketIO:

Package Downloads
StockSharp.AlphaVantage

AlphaVantage

StockSharp.IEX

Trading and algorithmic trading platform (stock markets, forex, bitcoins and options). .NET API for InteractiveBrokers, GainCapital, OANDA, FIX/FAST, Binance etc. More info on web site https://stocksharp.com/store/api/

StockSharp.Web.Api.Client

StockSharp WebApi

StockSharp.Binance

Binance

StockSharp.Okex

OKX connector

GitHub repositories (1)

Showing the top 1 popular GitHub repositories that depend on Ecng.Net.SocketIO:

Repository Stars
StockSharp/StockSharp
Algorithmic trading and quantitative trading open source platform to develop trading robots (stock markets, forex, crypto, bitcoins, and options).
Version Downloads Last Updated
1.0.533 77 2/4/2026
1.0.532 81 2/4/2026
1.0.531 256 2/1/2026
1.0.530 92 1/30/2026
1.0.529 89 1/30/2026
1.0.528 87 1/30/2026
1.0.527 99 1/29/2026
1.0.526 105 1/26/2026
1.0.525 89 1/26/2026
1.0.524 102 1/22/2026
1.0.523 96 1/22/2026
1.0.522 96 1/21/2026
1.0.521 123 1/19/2026
1.0.520 99 1/19/2026
1.0.519 99 1/18/2026
1.0.518 93 1/18/2026
1.0.517 100 1/16/2026
1.0.516 130 1/14/2026
1.0.515 101 1/13/2026
1.0.514 98 1/13/2026
1.0.513 104 1/12/2026
1.0.512 139 1/9/2026
1.0.511 121 1/9/2026
1.0.510 105 1/8/2026
1.0.509 109 1/8/2026
1.0.508 108 1/7/2026
1.0.507 107 1/6/2026
1.0.506 105 1/6/2026
1.0.505 110 1/5/2026
1.0.504 122 1/4/2026
1.0.503 124 1/1/2026
1.0.502 112 12/31/2025
1.0.501 114 12/30/2025
1.0.500 108 12/30/2025
1.0.499 118 12/29/2025
1.0.498 112 12/29/2025
1.0.497 115 12/26/2025
1.0.496 110 12/26/2025
1.0.495 107 12/26/2025
1.0.494 127 12/26/2025
1.0.493 200 12/25/2025
1.0.492 204 12/25/2025
1.0.491 213 12/24/2025
1.0.490 206 12/23/2025
1.0.489 194 12/22/2025
1.0.488 196 12/22/2025
1.0.487 200 12/22/2025
1.0.486 186 12/21/2025
1.0.485 241 12/19/2025
1.0.484 265 12/19/2025
1.0.483 303 12/18/2025
1.0.482 302 12/17/2025
1.0.481 303 12/15/2025
1.0.480 277 12/15/2025
1.0.479 262 12/14/2025
1.0.478 183 12/14/2025
1.0.477 180 12/13/2025
1.0.476 202 12/13/2025
1.0.475 169 12/12/2025
1.0.474 155 12/12/2025
1.0.473 144 12/12/2025
1.0.472 149 12/12/2025
1.0.471 144 12/12/2025
1.0.470 146 12/12/2025
1.0.469 150 12/12/2025
1.0.468 748 12/2/2025
1.0.467 706 12/2/2025
1.0.466 701 12/2/2025
1.0.465 304 11/30/2025
1.0.464 180 11/29/2025
1.0.463 169 11/28/2025
1.0.462 174 11/28/2025
1.0.461 218 11/27/2025
1.0.460 258 11/24/2025
1.0.459 229 11/24/2025
1.0.458 226 11/23/2025
1.0.457 200 11/23/2025
1.0.456 255 11/22/2025
1.0.455 462 11/20/2025
1.0.454 438 11/20/2025
1.0.453 436 11/20/2025
1.0.452 461 11/18/2025
1.0.451 443 11/18/2025
1.0.450 368 11/13/2025
1.0.449 305 11/10/2025
1.0.448 1,127 11/1/2025
1.0.447 232 10/31/2025
1.0.446 243 10/28/2025
1.0.445 363 10/27/2025
1.0.444 230 10/27/2025
1.0.443 162 10/25/2025
1.0.442 190 10/24/2025
1.0.441 297 10/20/2025
1.0.440 332 10/12/2025
1.0.439 179 10/11/2025
1.0.438 313 10/7/2025
1.0.437 256 10/6/2025
1.0.436 296 10/3/2025
1.0.435 267 10/1/2025
1.0.434 239 10/1/2025
1.0.433 239 9/30/2025
1.0.432 243 9/28/2025
1.0.431 258 9/25/2025
1.0.430 3,449 9/5/2025
1.0.429 274 9/2/2025
1.0.428 626 8/30/2025
1.0.427 294 8/30/2025
1.0.426 295 8/20/2025
1.0.425 239 8/20/2025
1.0.424 258 8/19/2025
1.0.423 262 8/15/2025
1.0.422 356 8/10/2025
1.0.421 1,073 7/16/2025
1.0.420 308 7/14/2025
1.0.419 280 7/13/2025
1.0.418 257 7/13/2025
1.0.417 229 7/12/2025
1.0.416 820 7/8/2025
1.0.415 292 7/4/2025
1.0.414 289 7/2/2025
1.0.413 450 6/24/2025
1.0.412 1,061 6/16/2025
1.0.411 445 6/9/2025
1.0.410 320 6/8/2025
1.0.409 645 5/21/2025
1.0.408 291 5/21/2025
1.0.407 276 5/17/2025
1.0.406 684 5/12/2025
1.0.405 376 5/12/2025
1.0.404 346 5/12/2025
1.0.403 266 5/11/2025
1.0.402 281 5/11/2025
1.0.401 236 5/10/2025
1.0.400 195 5/10/2025
1.0.399 321 5/6/2025
1.0.398 242 5/3/2025
1.0.397 410 4/17/2025
1.0.396 362 4/15/2025
1.0.395 259 4/12/2025
1.0.394 336 4/9/2025
1.0.393 293 4/6/2025
1.0.392 250 4/5/2025
1.0.391 1,125 3/22/2025
1.0.390 322 3/20/2025
1.0.389 309 3/20/2025
1.0.388 302 3/19/2025
1.0.387 868 2/26/2025
1.0.386 276 2/26/2025
1.0.385 796 2/8/2025
1.0.384 272 2/8/2025
1.0.383 257 2/8/2025
1.0.382 248 2/6/2025
1.0.381 240 2/6/2025
1.0.380 259 2/6/2025
1.0.379 267 2/6/2025
1.0.378 245 2/6/2025
1.0.377 245 2/5/2025
1.0.376 245 2/5/2025
1.0.375 266 2/5/2025
1.0.374 292 2/3/2025
1.0.373 273 2/2/2025
1.0.372 291 2/1/2025
1.0.371 278 1/31/2025
1.0.370 281 1/30/2025
1.0.369 262 1/26/2025
1.0.368 294 1/21/2025
1.0.367 278 1/20/2025
1.0.366 244 1/20/2025
1.0.365 259 1/19/2025
1.0.364 248 1/19/2025
1.0.363 276 1/15/2025
1.0.362 243 1/15/2025
1.0.361 237 1/14/2025
1.0.360 230 1/12/2025
1.0.359 221 1/12/2025
1.0.358 240 1/12/2025
1.0.357 206 1/12/2025
1.0.356 260 1/10/2025
1.0.355 1,093 12/30/2024
1.0.354 283 12/27/2024
1.0.353 302 12/19/2024
1.0.352 771 11/20/2024
1.0.351 278 11/19/2024
1.0.350 261 11/19/2024
1.0.349 823 11/18/2024
1.0.348 495 11/15/2024
1.0.347 245 11/14/2024
1.0.346 270 11/14/2024
1.0.345 278 11/14/2024
1.0.344 226 11/14/2024
1.0.343 258 11/14/2024
1.0.342 296 11/7/2024
1.0.341 306 10/31/2024
1.0.340 361 10/20/2024
1.0.339 283 10/20/2024
1.0.338 299 10/20/2024
1.0.337 287 10/19/2024
1.0.336 305 10/19/2024
1.0.335 305 10/19/2024
1.0.334 297 10/19/2024
1.0.333 298 10/19/2024
1.0.332 279 10/19/2024
1.0.331 309 10/19/2024
1.0.330 338 10/18/2024
1.0.329 291 10/17/2024
1.0.328 254 10/17/2024
1.0.327 279 10/17/2024
1.0.326 831 10/14/2024
1.0.325 259 10/13/2024
1.0.324 257 10/13/2024
1.0.323 274 10/12/2024
1.0.322 471 10/9/2024
1.0.321 275 10/9/2024
1.0.320 467 10/5/2024
1.0.319 798 9/18/2024
1.0.318 254 9/18/2024
1.0.317 279 9/18/2024
1.0.316 271 9/17/2024
1.0.315 772 9/3/2024
1.0.314 320 9/1/2024
1.0.313 988 8/9/2024
1.0.312 279 8/9/2024
1.0.311 294 8/8/2024
1.0.310 737 7/25/2024
1.0.309 297 7/23/2024
1.0.308 318 7/17/2024
1.0.307 589 7/4/2024
1.0.306 643 6/12/2024
1.0.305 281 6/12/2024
1.0.304 285 6/12/2024
1.0.303 479 5/28/2024
1.0.302 638 5/4/2024
1.0.301 432 4/23/2024
1.0.300 294 4/21/2024
1.0.299 324 4/14/2024
1.0.298 592 3/28/2024
1.0.297 360 3/17/2024
1.0.296 561 3/9/2024
1.0.295 379 2/23/2024
1.0.294 308 2/23/2024
1.0.293 520 2/18/2024
1.0.292 312 2/18/2024
1.0.291 290 2/17/2024
1.0.290 305 2/16/2024
1.0.289 425 2/14/2024
1.0.288 303 2/13/2024
1.0.287 376 2/8/2024
1.0.286 376 2/5/2024
1.0.285 293 2/4/2024
1.0.284 465 1/23/2024
1.0.283 287 1/23/2024
1.0.282 357 1/12/2024
1.0.281 722 1/2/2024
1.0.280 333 12/29/2023
1.0.279 387 12/17/2023
1.0.278 546 12/15/2023
1.0.277 311 12/15/2023
1.0.276 291 12/15/2023
1.0.275 327 12/13/2023
1.0.274 322 12/13/2023
1.0.273 327 12/10/2023
1.0.272 696 11/18/2023
1.0.271 238 11/18/2023
1.0.270 266 11/18/2023
1.0.269 248 11/17/2023
1.0.268 221 11/12/2023
1.0.267 219 11/12/2023
1.0.266 249 11/10/2023
1.0.265 205 11/10/2023
1.0.264 247 11/9/2023
1.0.263 209 11/9/2023
1.0.262 226 11/9/2023
1.0.261 256 11/3/2023
1.0.260 237 11/1/2023
1.0.259 225 11/1/2023
1.0.258 1,482 9/8/2023
1.0.257 278 9/8/2023
1.0.256 294 9/3/2023
1.0.255 363 8/27/2023
1.0.254 290 8/24/2023
1.0.253 257 8/21/2023
1.0.252 333 8/15/2023
1.0.251 301 8/14/2023
1.0.250 276 8/14/2023
1.0.249 312 8/10/2023
1.0.248 1,031 7/29/2023
1.0.247 1,107 7/1/2023
1.0.246 319 6/29/2023
1.0.245 816 5/27/2023
1.0.244 368 5/21/2023
1.0.243 305 5/19/2023
1.0.242 1,095 5/8/2023
1.0.241 366 5/7/2023
1.0.240 356 5/7/2023
1.0.239 334 5/7/2023
1.0.238 381 5/1/2023
1.0.237 424 4/22/2023
1.0.236 383 4/21/2023
1.0.235 350 4/21/2023
1.0.234 1,246 4/13/2023
1.0.233 1,145 4/3/2023
1.0.232 501 3/27/2023
1.0.231 443 3/21/2023
1.0.230 447 3/17/2023
1.0.229 439 3/13/2023
1.0.228 1,194 3/6/2023
1.0.227 506 2/26/2023
1.0.226 949 2/21/2023
1.0.225 463 2/20/2023
1.0.224 479 2/16/2023
1.0.223 468 2/15/2023
1.0.222 440 2/14/2023
1.0.221 441 2/14/2023
1.0.220 1,370 2/9/2023
1.0.219 848 2/7/2023
1.0.218 499 2/4/2023
1.0.217 485 2/4/2023
1.0.216 495 2/3/2023
1.0.215 459 2/3/2023
1.0.214 453 2/3/2023
1.0.213 896 2/2/2023
1.0.212 845 1/30/2023
1.0.211 479 1/30/2023
1.0.210 522 1/25/2023
1.0.209 515 1/23/2023
1.0.208 465 1/23/2023
1.0.207 500 1/18/2023
1.0.206 527 1/15/2023
1.0.205 529 1/6/2023
1.0.204 1,432 1/1/2023
1.0.203 496 12/31/2022
1.0.202 981 12/30/2022
1.0.201 515 12/29/2022
1.0.200 519 12/23/2022
1.0.199 1,403 12/12/2022
1.0.198 1,081 12/8/2022
1.0.197 496 12/4/2022
1.0.196 502 12/4/2022
1.0.195 506 12/2/2022
1.0.194 530 11/30/2022
1.0.193 492 11/29/2022
1.0.192 489 11/28/2022
1.0.191 528 11/26/2022
1.0.190 526 11/26/2022
1.0.189 530 11/25/2022
1.0.188 528 11/25/2022
1.0.187 542 11/18/2022
1.0.186 1,613 11/11/2022
1.0.185 564 11/11/2022
1.0.184 518 11/10/2022
1.0.183 581 11/5/2022
1.0.182 563 11/4/2022
1.0.181 542 11/2/2022
1.0.180 535 11/2/2022
1.0.179 1,443 11/1/2022
1.0.178 1,670 10/16/2022
1.0.177 759 9/25/2022
1.0.176 687 9/10/2022
1.0.175 2,994 9/8/2022
1.0.174 666 9/8/2022
1.0.173 671 9/8/2022
1.0.172 648 9/4/2022
1.0.171 644 9/4/2022
1.0.170 5,365 8/24/2022
1.0.169 729 8/8/2022
1.0.168 650 8/8/2022
1.0.167 1,277 7/31/2022
1.0.166 666 7/31/2022
1.0.165 679 7/26/2022
1.0.164 647 7/26/2022
1.0.163 3,213 7/21/2022
1.0.162 700 7/19/2022
1.0.161 3,171 7/18/2022
1.0.160 702 7/13/2022
1.0.159 686 7/8/2022
1.0.158 711 6/30/2022
1.0.157 716 6/20/2022
1.0.156 667 6/18/2022
1.0.155 711 6/6/2022
1.0.154 759 5/27/2022
1.0.153 5,230 4/30/2022
1.0.152 694 4/20/2022
1.0.151 726 4/10/2022
1.0.150 693 4/7/2022
1.0.149 673 4/7/2022
1.0.148 733 4/2/2022
1.0.147 692 3/29/2022
1.0.146 677 3/27/2022
1.0.145 683 3/27/2022
1.0.144 3,933 3/24/2022
1.0.143 2,695 2/20/2022
1.0.142 654 2/20/2022
1.0.141 665 2/20/2022
1.0.140 695 2/20/2022
1.0.139 716 2/20/2022
1.0.138 681 2/20/2022
1.0.137 674 2/20/2022
1.0.136 695 2/20/2022
1.0.135 697 2/20/2022
1.0.134 686 2/19/2022
1.0.133 4,579 2/10/2022
1.0.132 797 1/27/2022
1.0.131 719 1/27/2022
1.0.130 3,580 1/24/2022
1.0.129 667 1/24/2022
1.0.128 706 1/23/2022
1.0.127 7,030 12/29/2021
1.0.126 554 12/27/2021
1.0.125 496 12/27/2021
1.0.124 519 12/27/2021
1.0.123 1,778 12/20/2021
1.0.122 563 12/17/2021
1.0.121 552 12/16/2021
1.0.120 534 12/15/2021
1.0.119 519 12/14/2021
1.0.118 544 12/14/2021
1.0.117 502 12/13/2021
1.0.116 668 12/12/2021
1.0.115 1,643 12/10/2021
1.0.114 551 12/7/2021
1.0.113 550 12/7/2021
1.0.112 1,987 12/6/2021
1.0.111 549 12/6/2021
1.0.110 555 12/5/2021
1.0.109 1,246 12/3/2021
1.0.108 1,051 12/3/2021
1.0.107 584 12/2/2021
1.0.106 2,470 11/29/2021
1.0.105 5,277 11/23/2021
1.0.104 541 11/23/2021
1.0.103 1,632 11/22/2021
1.0.102 638 11/17/2021
1.0.101 592 11/14/2021
1.0.100 1,761 11/13/2021
1.0.99 606 11/11/2021
1.0.98 586 11/11/2021
1.0.97 569 11/10/2021
1.0.96 584 11/9/2021
1.0.95 2,615 11/6/2021
1.0.94 615 11/6/2021
1.0.93 2,187 11/5/2021
1.0.92 641 11/5/2021
1.0.91 603 11/4/2021
1.0.90 569 11/4/2021
1.0.89 633 11/3/2021
1.0.88 693 10/30/2021
1.0.87 2,057 10/21/2021
1.0.86 665 10/17/2021
1.0.85 676 10/17/2021
1.0.84 3,064 10/14/2021
1.0.83 602 10/13/2021
1.0.82 625 10/13/2021
1.0.81 596 10/12/2021
1.0.80 2,152 10/11/2021
1.0.79 582 10/9/2021
1.0.78 1,964 10/7/2021
1.0.77 2,169 10/7/2021
1.0.76 582 10/7/2021
1.0.75 616 10/6/2021
1.0.74 671 9/28/2021
1.0.73 2,380 9/23/2021
1.0.72 715 9/11/2021
1.0.71 617 9/10/2021
1.0.70 682 9/9/2021
1.0.69 584 9/8/2021
1.0.68 647 9/8/2021
1.0.67 2,170 9/6/2021
1.0.66 715 8/31/2021
1.0.65 574 8/30/2021
1.0.64 2,627 7/31/2021
1.0.63 3,058 7/30/2021
1.0.62 695 7/26/2021
1.0.61 4,492 7/5/2021
1.0.60 653 7/1/2021
1.0.59 3,835 6/4/2021
1.0.58 5,086 4/26/2021
1.0.57 2,196 4/19/2021
1.0.56 5,740 4/8/2021
1.0.55 1,820 4/7/2021
1.0.54 634 4/7/2021
1.0.53 1,897 4/3/2021
1.0.52 7,997 3/22/2021
1.0.51 5,788 3/4/2021
1.0.50 2,173 2/26/2021
1.0.49 8,290 2/2/2021
1.0.48 3,245 1/26/2021
1.0.47 3,016 1/24/2021
1.0.46 675 1/24/2021
1.0.45 724 1/23/2021
1.0.44 3,917 1/20/2021
1.0.43 728 1/20/2021
1.0.42 2,100 1/18/2021
1.0.41 642 1/18/2021
1.0.40 2,073 1/16/2021
1.0.39 6,329 12/17/2020
1.0.38 705 12/16/2020
1.0.37 3,229 12/14/2020
1.0.36 2,137 12/9/2020
1.0.35 688 12/9/2020
1.0.34 701 12/7/2020
1.0.33 802 12/6/2020
1.0.32 755 12/2/2020
1.0.31 719 12/2/2020
1.0.30 2,217 12/1/2020
1.0.29 7,379 11/12/2020
1.0.29-atestpub 578 11/11/2020
1.0.28 3,362 10/11/2020
1.0.27 8,628 9/9/2020
1.0.26 2,644 9/3/2020
1.0.25 2,705 8/20/2020
1.0.24 6,174 8/9/2020
1.0.23 2,720 7/28/2020
1.0.22 2,657 7/19/2020
1.0.21 4,472 7/6/2020
1.0.20 6,642 6/6/2020
1.0.19 2,632 6/4/2020
1.0.18 4,398 5/29/2020
1.0.17 4,438 5/21/2020
1.0.16 777 5/17/2020
1.0.15 4,532 5/12/2020
1.0.14 8,250 5/4/2020
1.0.13 801 4/24/2020
1.0.12 791 4/22/2020
1.0.11 765 4/22/2020
1.0.10 788 4/21/2020
1.0.9 3,241 4/18/2020
1.0.8 2,599 4/16/2020
1.0.7 799 4/16/2020
1.0.6 2,273 4/15/2020
1.0.5 2,682 4/11/2020
1.0.4 2,574 4/3/2020
1.0.3 796 4/1/2020
1.0.2 2,504 3/27/2020
1.0.1 2,616 3/22/2020
1.0.0 903 3/22/2020

Make WebSocketClient stateChanged and error callbacks async with CancellationToken support