Skip to content

marcschier/mqtt-client

Repository files navigation

Mqtt.Client

A high-performance, low-allocation MQTT 3.1.1 + 5.0 client for .NET — designed to feel like System.Threading.Channels.

CI NuGet GitHub Packages

🚀 Highlights

  • Multi-TFM: netstandard2.0, netstandard2.1, net8.0, net9.0, net10.0 (NativeAOT-clean on net10.0; WebSocket transport requires netstandard2.1+).
  • Channels-style APIChannelReader<MqttMessage> for subscriptions, TryPublish / PublishAsync for sending.
  • Built-in DI extensions, source-generated logging, System.Diagnostics.Metrics, ActivitySource.
  • Transports: TCP, TLS, WebSocket, Secure WebSocket.
  • SOCKS5 proxy (RFC 1928, with optional RFC 1929 username/password auth) for TCP/TLS.
  • Auto-reconnect with exponential backoff + jitter; queued publishes survive reconnect.
  • Pluggable session persistence for QoS 1/2 in-flight state.
  • Secure defaults — TLS 1.2/1.3, CRL checking, capped incoming packet size.

📦 Install

dotnet add package Mqtt.Client

⚡ Quickstart

using Mqtt.Client;

await using var client = MqttClient.CreateBuilder()
    .ConnectTo("mqtts://broker:8883")
    .WithClientId("svc-1")
    .WithCredentials("user", "pw")
    .Build();

await client.ConnectAsync();

await using var sub = await client.SubscribeAsync("sensors/+/temp");
await foreach (var msg in sub.Reader.ReadAllAsync())
{
    using (msg)   // payloads are pooled by default — dispose after use, don't retain
    {
        Console.WriteLine($"{msg.Topic}: {msg.Payload.Length} bytes");
    }
}

await client.PublishAsync("commands/svc-1", "ping"u8.ToArray());

Low-allocation extras

// Publish a payload that's already split across buffers — no concatenation needed.
ReadOnlySequence<byte> framed = BuildFramedPayload();
await client.PublishAsync("telemetry", framed, MqttQoS.AtLeastOnce);

// Inline-handler subscription: the payload is a true zero-copy slice of the receive buffer,
// valid only inside the handler (no allocation, nothing to dispose). Back-pressure flows to
// the broker while the handler runs.
await client.SubscribeAsync("telemetry/#", msg =>
{
    Process(msg.PayloadMemory.Span);   // do not retain msg or its payload
    return ValueTask.CompletedTask;
});

// Channel subscriptions pool the payload by default (dispose each message). If you need to
// retain messages freely instead, opt back into garbage-collected payloads:
var retaining = MqttClient.CreateBuilder()
    .ConnectTo("mqtt://broker:1883")
    .Configure(o => o.RetainableInboundMessages = true)
    .Build();

📚 Documentation

🔍 When to pick MQTTnet instead

MQTTnet is a mature, battle-tested .NET MQTT library that covers ground this client intentionally doesn't:

  • You need a broker in addition to a client.
  • You need ASP.NET Core integration (managed clients, hosted broker, middleware).
  • You need the broadest possible protocol option coverage and a long support history.
  • You're already on it and it serves you well.

Mqtt.Client is focused on being a small, fast, AOT-friendly, channels-style client library for .NET services. Pick whichever fits your situation; both projects are MIT-licensed and the protocol wire formats are identical.

🔐 Security

Found something? Please file privately via GitHub Security Advisories — see SECURITY.md.

🔏 Strong naming

The published Mqtt.Client and Mqtt.Client.Testing assemblies are strong-named, so they can be referenced from other strong-named projects. The public key token is 7101d3319b65c487.

Strong naming is an assembly identity feature, not a security boundary: it does not authenticate the publisher, and the packages are not Authenticode- or NuGet-signed. The signing key (Mqtt.Client.snk) is committed to this repository and is intentionally not a secret. The same key is reused for every release so the strong-name identity stays stable across versions.

About

High-performance, low-allocation MQTT 3.1.1 + 5.0 client for .NET. Channels-style API, NativeAOT-ready.

Resources

License

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages