Pacem.Extensions.Sockets 0.10.15-euler

Suggested Alternatives

Pacem.Net.Sockets

This is a prerelease version of Pacem.Extensions.Sockets.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Pacem.Extensions.Sockets --version 0.10.15-euler
                    
NuGet\Install-Package Pacem.Extensions.Sockets -Version 0.10.15-euler
                    
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="Pacem.Extensions.Sockets" Version="0.10.15-euler" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Pacem.Extensions.Sockets" Version="0.10.15-euler" />
                    
Directory.Packages.props
<PackageReference Include="Pacem.Extensions.Sockets" />
                    
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 Pacem.Extensions.Sockets --version 0.10.15-euler
                    
#r "nuget: Pacem.Extensions.Sockets, 0.10.15-euler"
                    
#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 Pacem.Extensions.Sockets@0.10.15-euler
                    
#: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=Pacem.Extensions.Sockets&version=0.10.15-euler&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Pacem.Extensions.Sockets&version=0.10.15-euler&prerelease
                    
Install as a Cake Tool

Pacem.Extensions.Sockets

A small, dependable TCP/IP client connection for long-lived links to appliances that speak a line- or frame-oriented protocol over a raw socket — domotic gateways, PLCs, meters.

It gives you one thing well: a connection that stays up. Connect, send, receive, and — in keep-alive mode — reconnect on its own when the peer disappears, without spinning the CPU and without ever blocking the caller waiting for an appliance to come back.

Install

dotnet add package Pacem.Extensions.Sockets

Targets net10.0. The only dependency is Microsoft.Extensions.DependencyInjection.Abstractions.

Quick start

services.AddPacemTcpIp();
public sealed class MeterReader(ITcpIpConnectionFactory factory) : IDisposable
{
    private readonly ITcpIpConnection _connection = factory.CreateConnection(options =>
    {
        options.Host = "172.24.0.100";
        options.Port = 20000;
        options.Mode = TcpIpConnectionMode.KeepAlive;
        options.OnConnectedAsync = () => { /* handshake */ return Task.CompletedTask; };
        options.OnErrorAsync = exc => { /* log */ return Task.CompletedTask; };
    });

    public async Task StartAsync()
    {
        await _connection.OpenAsync();
        if (_connection.IsConnected)
        {
            _connection.StartReceiving(bytes => Handle(bytes));
        }
    }

    public void Dispose() => _connection.Dispose();
}

Connection modes

Mode Behaviour
Default One connection attempt. A dropped link stays dropped.
KeepAlive Liveness beat, plus automatic reconnection with exponential back-off.

OpenAsync never waits for an absent peer

In KeepAlive mode OpenAsync makes one attempt and returns. If it fails, retries continue in the background and the task still completes — so a request handler calling into this never hangs because an appliance is offline.

Always check IsConnected after awaiting it:

await connection.OpenAsync();
if (!connection.IsConnected)
{
    // not fatal: the background loop keeps trying
}

Back-off starts at ReconnectDelay, doubles per failure, and is capped at MaxReconnectDelay. CloseAsync() and Dispose() stop it for good; a later OpenAsync() starts over.

Receiving: framing is yours

StartReceiving hands you buffers exactly as they come off the socket. TCP is a byte stream with no message boundaries, so one read may carry half a message, or five of them. Re-assembling is the caller's job — the connection will not guess where your messages end.

connection.StartReceiving(chunk =>
{
    foreach (var message in _framer.Push(chunk))   // your framing
    {
        Handle(message);
    }
});

Reset your framer on OnConnectedAsync / OnDisconnectedAsync: a reconnection restarts the byte stream and any half-received message is void.

Calling StartReceiving twice without an intervening StopReceiving is a no-op — a second pump would steal bytes from the first.

Options

Option Default Notes
Host, Port — Required.
Mode Default See above.
UseSsl false Certificate validation is strict; self-signed peers are rejected.
ConnectTimeout 10 s Per attempt.
KeepAliveTimespan 10 s Liveness period; floored at 1 s.
KeepAliveContent null Optional bytes sent on every beat.
ReconnectDelay 1 s First back-off step.
MaxReconnectDelay 30 s Back-off ceiling.
SendBufferSize, ReceiveBufferSize 8192 Socket buffers.

Handlers

OnConnectedAsync, OnDisconnectedAsync, OnCloseAsync, OnReceivedAsync, OnErrorAsync.

Handlers are awaited on the connection's own loops. A handler that throws is reported through OnErrorAsync and never takes the connection down — but a slow handler does hold up the receive pump, so offload real work.

OnDisconnectedAsync fires on both an unsolicited drop and an explicit CloseAsync; OnCloseAsync fires only on the latter.

Behaviour worth knowing

  • Sends are serialized. A keep-alive beat cannot interleave with an application write, so frames never get spliced together on the wire.
  • SendAsync on a closed connection throws InvalidOperationException. A failure during a send is reported via OnErrorAsync and treated as a drop instead.
  • Liveness is detected by polling for a readable socket with nothing to read, which is what actually catches a peer that went away.
  • Dispose is idempotent and stops everything: pump, beat, reconnection.

Threading

One connection instance is safe to use from several callers: SendAsync serializes, StartReceiving / StopReceiving / CloseAsync / Dispose are guarded. The registered ITcpIpConnectionFactory is a singleton; connections themselves are not pooled — you own each one you create, and you dispose it.

License

Apache 2.0.

Product Compatible and additional computed target framework versions.
.NET 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.10.19-cardano 170 10/26/2026 0.10.19-cardano is deprecated because it is no longer maintained.
0.10.19-bombelli 122 10/20/2026 0.10.19-bombelli is deprecated because it is no longer maintained.
0.10.18 120 10/14/2026 0.10.18 is deprecated because it is no longer maintained.
0.10.18-venn 116 10/9/2026 0.10.18-venn is deprecated because it is no longer maintained.
0.10.18-turing 124 10/8/2026 0.10.18-turing is deprecated because it is no longer maintained.
0.10.18-selberg 127 10/1/2026 0.10.18-selberg is deprecated because it is no longer maintained.
0.10.18-riemann 127 9/26/2026 0.10.18-riemann is deprecated because it is no longer maintained.
0.10.18-pascal 131 9/21/2026 0.10.18-pascal is deprecated because it is no longer maintained.
0.10.17 133 9/18/2026 0.10.17 is deprecated because it is no longer maintained.
0.10.17-foucault 130 9/18/2026 0.10.17-foucault is deprecated because it is no longer maintained.
0.10.16 128 9/16/2026 0.10.16 is deprecated because it is no longer maintained.
0.10.16-hamilton 118 9/14/2026 0.10.16-hamilton is deprecated because it is no longer maintained.
0.10.16-gauss 127 9/14/2026 0.10.16-gauss is deprecated because it is no longer maintained.
0.10.16-faraday 136 9/9/2026 0.10.16-faraday is deprecated because it is no longer maintained.
0.10.15 140 9/7/2026 0.10.15 is deprecated because it is no longer maintained.
0.10.15-euler 146 9/7/2026 0.10.15-euler is deprecated because it is no longer maintained.
0.10.14 126 9/6/2026 0.10.14 is deprecated because it is no longer maintained.
0.10.14-dedekind 144 9/6/2026 0.10.14-dedekind is deprecated because it is no longer maintained.
0.10.14-cauchy 135 9/5/2026 0.10.14-cauchy is deprecated because it is no longer maintained.
0.10.14-boltzmann 122 9/5/2026 0.10.14-boltzmann is deprecated because it is no longer maintained.
Loading failed