socket.io-client-csharp

repository·master·Indexed 21 days ago

https://github.com/doghappy/socket.io-client-csharp

A C# client for Socket.IO supporting server versions 2, 3, and 4. It features support for HTTP polling and WebSocket transports with automatic upgrades, binary message handling, and customizable JSON serializers (System.Text.Json or Newtonsoft.Json). The library includes support for acknowledgments, proxy configuration, and integration with Microsoft.Extensions.Logging.

Tokens
2.6K
Snippets
8
Records
8
Agent score
24%

What's inside socket.io-client-csharp

  1. Use Acknowledgments (Ack)

    master

    Acknowledgments allow for two-way communication during event emission.

    1. Client-to-Server Ack

    Emit an event with a callback. The server processes the event and invokes the callback with data.

    await client.EmitAsync("hi", ["Hi, I'm Client"], ack =>
    {
        var message1 = ack.GetValue<string>(0)!;
        var message2 = ack.GetValue<string>(1)!;
        return Task.CompletedTask;
    });

    2. Server-to-Client Ack

    Listen for an event that includes a callback. After processing, the client sends data back to the server using ctx.SendAckDataAsync(data).

    client.On("add", async ctx =>
    {
        var a = ctx.GetValue<int>(0);
        var b = ctx.GetValue<int>(1);
        await ctx.SendAckDataAsync([a + b]);
    });
    // Client emitting with Ack
    await client.EmitAsync("hi", ["Hi, I'm Client"], ack =>
    {
        var message1 = ack.GetValue<string>(0)!;
        var message2 = ack.GetValue<string>(1)!;
        return Task.CompletedTask;
    });
    
    // Client listening for Ack
    client.On("add", async ctx =>
    {
        var a = ctx.GetValue<int>(0);
        var b = ctx.GetValue<int>(1);
        await ctx.SendAckDataAsync([a + b]);
    });
  2. Enable internal logging

    master

    Use the Microsoft.Extensions.Logging integration to observe internal client behavior. You can set the minimum log level (e.g., LogLevel.Trace) to see detailed logs.

    var client = new SocketIO(new Uri("http://localhost:11400"), new SocketIOOptions(), services =>
    {
        services.AddLogging(builder =>
        {
            builder.SetMinimumLevel(LogLevel.Trace);
            builder.AddConsole();
        });
    });
  3. Configure a Proxy

    master

    To communicate through a proxy (useful for specific network environments or debugging), configure the HttpClientHandler for polling or WebSocketOptions for WebSockets.

    // Proxy for Http Polling
    var client = new SocketIO(new Uri("http://localhost:11400"), services =>
    {
        services.AddSingleton<HttpClient>(_ =>
        {
            var handler = new HttpClientHandler
            {
                Proxy = new WebProxy(proxyUrl),
                UseProxy = true
            };
            return new HttpClient(handler);
        });
    });
    
    // Proxy for WebSocket
    var client = new SocketIO(new Uri("http://localhost:11400"), services =>
    {
        services.AddSingleton(new WebSocketOptions
        {
            Proxy = new WebProxy(proxyUrl)
        });
    });
  4. Handle self-signed certificates

    master

    If your server uses a self-signed certificate, you must customize the validation logic for both HTTP Polling and WebSockets.

    Note: Since the client often starts with polling and upgrades to WebSocket, you should configure both to avoid connection failures.

    Important: When configuring WebSocket options, ensure you use SocketIOClient.Protocol.WebSocket.WebSocketOptions to avoid conflicts with System.Net.WebSockets.

    // For Http Polling
    var client = new SocketIO(new Uri("http://localhost:11400"), services =>
    {
        services.AddSingleton<HttpClient>(_ =>
        {
            var handler = new HttpClientHandler
            {
                ServerCertificateCustomValidationCallback = (s, cert, chain, policyError) => true // Implement logic
            };
            return new HttpClient(handler);
        });
    });
    
    // For WebSocket
    using SocketIOClient.Protocol.WebSocket;
    var client = new SocketIO(new Uri("http://localhost:11400"), services =>
    {
        services.AddSingleton(new WebSocketOptions
        {
            RemoteCertificateValidationCallback = (s, cert, chain, policyError) => true // Implement logic
        });
    });
  5. Quick start with SocketIOClient

    master

    To connect to a Socket.IO server, instantiate a SocketIO object with the server URI. You can listen for events using the .On method. The callback provides a context (ctx) from which you can retrieve the raw text or specific data items using .GetValue<T>(index).

    var client = new SocketIO(new Uri("http://localhost:11400"));
    
    client.On("event", ctx =>
    {
        // Access data by index
        var message = ctx.GetValue<string>(0)!;
        var id = ctx.GetValue<int>(1);
        var user = ctx.GetValue<User>(2)!;
    
        Console.WriteLine(message);
        return Task.CompletedTask;
    });
  6. Configure SocketIOOptions

    master

    You can customize the connection behavior by passing a SocketIOOptions object to the SocketIO constructor. Common configuration options include:

    OptionDefaultDescription
    Path/socket.ioThe service endpoint path.
    ReconnectiontrueWhether to retry connection on failure.
    ReconnectionAttempts10Maximum number of retry attempts.
    ReconnectionDelayMax5000Upper bound for the random reconnection delay.
    ConnectionTimeout30sTimeout duration for each connection attempt.
    QuerynullQuery string values to send before connection.
    EIOV4Engine.IO version. Set to 3 for Socket.IO server v2.x.
    ExtraHeadersnullRequest headers for the handshake phase.
    TransportPollingTransport protocol. Use TransportProtocol.WebSocket if the server only supports WebSockets.
    AutoUpgradetrueAutomatically upgrade from polling to WebSocket if supported.
    AuthnullConnection credentials (not supported when EIO = 3).
    var client = new SocketIO(new Uri("http://localhost:11400"), new SocketIOOptions
    {
        Query = new NameValueCollection
        {
            ["user"] = "Alice"
        },
        // ... other options
    });
  7. Send and receive binary messages

    master

    The client supports sending and receiving complex data types containing byte[]. By default, System.Text.Json is used. You can use [JsonPropertyName] to customize property names for serialization.

    class FileDTO
    {
        [JsonPropertyName("name")]
        public string Name { get; set; }
    
        [JsonPropertyName("mimeType")]
        public string MimeType { get; set; }
    
        [JsonPropertyName("bytes")]
        public byte[] Bytes { get; set; }
    }
    
    // Emitting binary data
    await client.EmitAsync("1:emit", [
        new FileDTO
        {
            Name = "template.html",
            MimeType = "text/html",
            Bytes = Encoding.UTF8.GetBytes("<div>test</div>")
        }
    ]);
    
    // Receiving binary data
    client.On("new files", ctx =>
    {
        var result = ctx.GetValue<FileDTO>();
        Console.WriteLine(Encoding.UTF8.GetString(result.Bytes));
    });
  8. Configure Serializers (System.Text.Json or Newtonsoft.Json)

    master

    You can swap the default System.Text.Json serializer for Newtonsoft.Json or provide custom JsonSerializerOptions via the dependency injection container in the SocketIO constructor.

    // Using custom System.Text.Json options
    var client = new SocketIO(new Uri("http://localhost:11400"), services =>
    {
        services.AddSystemTextJson(new JsonSerializerOptions
        {
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase
        });
    });
    
    // Using Newtonsoft.Json (requires SocketIOClient.Serializer.NewtonsoftJson package)
    var client = new SocketIO(new Uri("http://localhost:11400"), services =>
    {
        services.AddNewtonsoftJson(new JsonSerializerSettings());
    });